我正在使用 boost 线程来运行 opengl 函数,我的主线程旨在通过标准输入和输出与外部程序通信。原因是一旦 opengl 进入主循环,它就永远不会离开,但我需要一种方法来读取输入而不阻塞渲染。一旦程序接收到输入,主程序通过静态成员与opengl线程通信(简单地改变值)
class ARGraphicController
{
public:
ARGraphicController(int sw, int sh);
~ARGraphicController();
//...
void start(int argc, char *argv[]);
static void changeGen();
static bool genMove;
private:
//..
};
bool ARGraphicController::genMove;
void ARGraphicController::start(int argc, char *argv[])
{
//opengl initialization
//./
glutMainLoop();
}
这是我的主要
void main()
{
graphic_handler = new boost::thread(boost::bind(&ARGraphicController::start, &graphic_controller, argc, argv));
string command_line;
while(1)
{
getline(cin, command_line);
//process input command
//...
//...
if(command == "genmov"){
//change static variable to true
graphic_controller.changeGen();
while(1)
{
//until the thread change the static variable back to false
if(!graphic_controller.genMove)
{
//...
break;
}
}
}
}
delete graphic_handler;
}
我不明白的是,如果我这样做,changeGen() 不会更改静态变量的值:
void ARGraphicController::changeGen()
{
genMove = true;
}
但是当我添加一个 std::cout 时,值会改变..
void ARGraphicController::changeGen()
{
genMove = true;
std::cout<<"value is changed :)"<<std::endl;
}
我怀疑这与静态成员变量(本质上是全局变量)不是线程安全的事实有关吗?如果是这样,我该如何解决这个问题?还是有更好的方法来设计我的应用程序以在我的主线程和线程之间进行通信?
谢谢
最佳答案
欢迎来到memory ordering的精彩世界| .
这里的问题是,在您当前的设置中,您无法保证写入的值何时对其他线程可见。任何编译器、CPU、缓存或内存 Controller (以及可能的其他)都可以在此处插入优化,以防止更改在第二个线程中变得可见。除此之外,您还有一场数据竞赛。对 bool 的非同步访问适用于大多数现代架构,但可能会严重破坏其他架构。在 ISO-C++11 中,此类数据争用会立即导致未定义的行为。
解决方案是使用线程库。这里最简单的修复是简单地使用 atomic<bool>
对于静态变量。这将同时处理订购和访问问题。或者,考虑一种消息传递原语:
- 使用
boost::future
发出一次性事件的信号。 - 使用
boost::condition_variable
表示线程可以等待的重复条件(生产者-消费者是这里的突出示例) - 使用来自 boost.lockfree 的无锁队列在发送大量统一消息时在线程之间建立数据流。
关于c++ - 在boost线程中更改静态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17270399/