在C++ 11中处理互斥

sor*_*h-r 9 c++ multithreading mutual-exclusion c++11

我有一个代表有限状态机的类,它应该在永久循环中运行并检查它的当前状态.在每个状态机器中将设置它的下一个状态,或者进入idle状态或做一些工作.我想允许另一个线程在它运行时改变机器的状态.这将导致预期的竞争条件.所以我添加了一个互斥锁定/解锁包装循环的机器和公共方法,允许其他线程改变机器的当前状态.

class Robot
{
public:
    enum StateType {s1,s2,s3,idle,finish};
    void run();
    void move();
private:
    StateType currentState;
    StateType nextState;
    StateType previousState;
    std::mutex mutal_state;
};
Run Code Online (Sandbox Code Playgroud)

执行:

void Robot::run()
{
    this->currentState = s1;
    while(true)
    {
        mutal_state.lock();
        switch(currentState)
        {
        case s1:
            // do some useful stuff here...
            currentState = idle;
            nextState = s3;
            break;
        case s2:
            // do some other useful stuff here...
            currentState = idle;
            nextState = finish;
            break;
        case s3:
            // again, do some useful things...
            currentState = idle;
            nextState = s2;
            break;
        case idle:
            // busy waiting...
            std::cout << "I'm waiting" << std::endl;
            break;
        case finish:
            std::cout << "Bye" << std::endl;
            mutal_state.unlock();
            return;
        }
        mutal_state.unlock();
    }
}
Run Code Online (Sandbox Code Playgroud)

以及允许其他线程更改当前状态的move方法:

void Robot::move()
{
    mutal_state.lock();
    previousState = currentState; // Booommm
    currentState = nextState;
    mutal_state.unlock();
}
Run Code Online (Sandbox Code Playgroud)

我无法找到我做错的事情!程序在move()函数的第一行崩溃.另一方面,GDB不能使用C++ 11并且无法跟踪代码......

更新:

玩代码,我可以看到问题在于移动功能.当程序试图锁定代码片段时move(),崩溃.例如,如果移动是这样的:

void Robot::move()
{
    std::cout << "MOVE IS CALLED" << std::endl;
    mutal_state.lock();
    //previousState = currentState;
    //std::cout << "MOVING" << std::endl;
    //currentState = nextState;
    mutal_state.unlock();
}
Run Code Online (Sandbox Code Playgroud)

输出是:

s1
I'm waiting
I'm waiting
MOVE IS CALLED1
The program has unexpectedly finished.
Run Code Online (Sandbox Code Playgroud)

但什么时候move是一个简单的功能,没有做任何事情:

void Robot::move()
{
    std::cout << "MOVE IS CALLED" << std::endl;
    //mutal_state.lock();
    //previousState = currentState;
    //std::cout << "MOVING" << std::endl;
    //currentState = nextState;
    //mutal_state.unlock();
}
Run Code Online (Sandbox Code Playgroud)

程序同时运行.

Mat*_*t T 2

我的建议:

1)如果你没有调试器,你怎么能确定是第一行移动崩溃了?它总是会质疑你对代码所做的任何假设,除非你有确凿的证据支持它。

2)我会查看状态 s3 中任何有趣的代码,因为这是第一个 move 调用将执行的代码。到目前为止,s3 中的代码尚未运行。要么删除发布示例中的所有代码栏,以排除这种情况。

3)编译器可能会复制寄存器中的变量,您应该将所有状态声明为易失性,这样它就知道不要以这种方式优化。