【发布时间】:2012-03-27 06:11:44
【问题描述】:
我有一个代表有限状态机的类,它应该在一个永远循环中运行并检查它的当前状态。在每个状态机将设置它的下一个状态,要么进入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;
};
实施:
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();
}
}
以及允许其他线程改变当前状态的move方法:
void Robot::move()
{
mutal_state.lock();
previousState = currentState; // Booommm
currentState = nextState;
mutal_state.unlock();
}
我无法找到我做错了什么!程序在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();
}
输出是:
s1
I'm waiting
I'm waiting
MOVE IS CALLED1
The program has unexpectedly finished.
但是当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();
}
程序同时运行。
【问题讨论】:
-
你试过用打印语句调试吗?
-
@FrustratedWithFormsDesigner:是的。我知道“爆炸”只会在某个线程尝试调用
move时发生。 -
你使用什么编译器版本?
-
@ildjarn:我使用的是 gcc 版本 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3),线程模型是 posix
-
您最好开始使用锁防护装置(例如
std::lock_guard<std::mutex>、std::unique_lock<std::mutex>),而不是手动锁定和解锁。这可能对您的直接问题没有帮助,但只能帮助维护/静态验证。更不用说异常安全了。
标签: c++ multithreading c++11 mutual-exclusion