在boost线程中更改静态变量

时间:2013-06-24 07:46:08

标签: c++ thread-safety boost-thread static-members

我正在使用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;
}

我怀疑它与静态成员变量(本质上是全局变量)不是线程安全的事实有关吗?如果是这样,我该如何解决这个问题呢?或者有更好的方法来设计我的主要和线程之间的通信应用程序吗?

由于

1 个答案:

答案 0 :(得分:1)

欢迎来到memory ordering的精彩世界。

这里的问题是,在您当前的设置中,当写入的值对另一个线程可见时,您无法保证。任何编译器,CPU,高速缓存或内存控制器(以及可能的其他)都可以在此处插入优化,以防止更改在第二个线程中变为可见。除此之外,您还有数据竞争。对bool的不同步访问将适用于大多数现代架构,但可能会在其他架构上恶意破坏。在ISO-C ++ 11中,此类数据争用会立即导致未定义的行为。

解决方案是使用线程库。这里最简单的解决方法是简单地使用atomic<bool>作为静态变量。这将解决订购和访问问题。或者,考虑一个消息传递原语:

  • 使用boost::future表示一次性事件。
  • 使用boost::condition_variable来表示线程可以等待的重复出现的情况(生产者 - 消费者就是这里的突出例子)
  • 使用boost.lockfree中的lockfree队列在发送大量统一消息时在线程之间建立数据流。