以下是安全的吗?
我是线程新手,我想将一个耗时的过程委托给我的C++程序中的一个单独的线程.使用boost库我编写了类似这样的代码:
thrd = new boost :: thread(boost :: bind(&myclass :: mymethod,this,&finished_flag);
其中finished_flag是我班级的布尔成员.线程完成后,它会设置值,程序的主循环会检查该值的变化.我认为这是可以的,因为我只启动一个线程,并且该线程是唯一改变值的东西(除非在我启动线程之前初始化它)所以这没关系,或者我错过了什么,并且需要使用锁和互斥锁等
你从来没有提到过finished_flag的类型......
如果它是一个直接的bool,那么它可能会起作用,但由于几个原因,它肯定是不好的做法.首先,一些编译器将缓存finished_flag变量的读取,因为编译器并不总是接受由另一个线程写入的事实.你可以通过声明bool 挥发来解决这个问题,但这会让我们走错方向.即使读取和写入正如您所期望的那样发生,也没有什么可以阻止OS调度程序在读/写中途交错两个线程.这可能不是一个问题,你在一个单独的线程中有一个读操作和一个写操作,但是你的意思是继续开始是一个好主意.
另一方面,如果它是一个线程安全的类型,就像MFC中的CEvent(或者在boost中的等效)那么你应该没问题.这是最好的方法:使用线程安全的同步对象进行线程间通信,即使对于简单的标志也是如此.
而不是使用成员变量来表示线程已完成,为什么不使用condition
?您已经在使用boost库,它condition
是线程库的一部分.
检查出来.它允许工作线程"发出信号"已完成,并且主线程可以在执行期间检查条件是否已经发出信号,然后执行它对完成的工作所需的任何操作.链接中有一些例子.
作为一般情况,我将假设资源只会被线程修改.你可能知道它是什么,但是其他人可能不会 - 因为主线程认为工作已经完成并试图访问不正确的数据而导致悲痛的结局!它甚至可能在工作线程仍在使用它时删除它,并导致应用程序崩溃.使用一个condition
将有助于此.
查看thread
文档,您也可以thread.timed_join
在主线程中调用.timed_join
将等待线程的指定金额'加入'(连接意味着该线程已finsihed)
如果你真的想通过共享内存深入了解线程之间的通信细节,即使编译确实使用适当的访问语义来确保它不会获得过时的数据版本,即使声明变量volatile也是不够的.检查完国旗后.CPU可以无序地发出读写错误(x86通常不会,但PPC肯定会这样做)并且C++ 9x中没有任何内容允许编译器生成代码以适当地命令内存访问.
Herb Sutter的Effective Concurrency系列深入探讨了C++世界如何与多核/多处理器世界相交叉.
我并不是要推定,但似乎你的finished_flag变量的目的是暂停主线程(在某些时候),直到线程thrd完成.
最简单的方法是使用boost :: thread :: join
// launch the thread... thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag); // ... do other things maybe ... // wait for the thread to complete thrd.join();