C++ Thread question - setting a value to indicate the thread has finished以下安全吗?
我是线程技术的新手,我想将耗时的过程委托给C ++程序中的单独线程。 thrd =新的boost :: thread(boost :: bind(&myclass :: mymethod,this,&finished_flag);
其中finish_flag是类的布尔成员。 线程完成后,它会设置该值,然后程序的主循环会检查该值是否有变化。 您从未提到过finish_flag的类型... 如果这是直言不讳的话,那么它可能会起作用,但是出于多种原因,这无疑是一种不好的做法。首先,一些编译器将缓存Finished_flag变量的读取,因为编译器并不总是能够理解它是由另一个线程写入的。您可以通过声明布尔变量来解决此问题,但这使我们走错了方向。即使发生了您期望的读写操作,也没有什么可以阻止OS调度程序在读/写过程中将两个线程交织在一起。在您在单独的线程中进行一次读取和一次写入操作的情况下,这可能不是问题,但是从您要继续进行的角度出发,这是一个好主意。 另一方面,如果它是线程安全的类型,例如MFC中的CEvent(或boost中的等效),则应该没问题。这是最好的方法:使用线程安全的同步对象进行线程间通信,即使是简单的标志也是如此。
为什么不使用 一探究竟。它允许工作线程"完成""信号",并且主线程可以在执行过程中检查是否已发出条件信号,然后对完成的工作做任何必要的事情。链接中有示例。
通常,我需要假设资源只能由线程修改。您可能知道它的用途,但其他人则可能不会—不会引起悲伤,因为主线程认为工作已完成,并尝试访问不正确的数据!当工作线程仍在使用它时,它甚至可能将其删除,并导致应用崩溃。使用
查看 我并不是要假设,但是似乎您的finish_flag变量的目的是暂停主线程(在某个时候),直到线程thrd完成为止。 最简单的方法是使用boost :: thread :: join
如果您确实想了解通过共享内存进行的线程之间通信的详细信息,即使声明变量volatile也是不够的,即使编译器确实使用了适当的访问语义来确保不会获得陈旧的数据版本也是如此。在检查标志之后。 CPU可以发出混乱的读写命令(x86通常不会发出命令,但是PPC确实可以发出命令),并且C ++ 9x中没有任何东西允许编译器生成代码来适当地排序内存访问。 Herb Sutter的有效并发系列非常深入地探讨了C ++世界如何与多核/多处理器世界相交。 使线程在退出之前设置标志(或发出事件信号)是一种竞争条件。线程不一定已经返回操作系统,并且可能仍在执行。 例如,考虑一个加载动态库(伪代码)的程序:
并假设该库使用您的线程:
当
解决方法是让 |