我有一个多线程C应用程序,如下所示(其中S是全局共享变量):

Thread 1   Thread 2   Thread 3       Thread 4

while(1)   while(1)    while(1)       while(1)
 read S     read S      read S
   |          |          |             sleep 1 second
   |          |          |             stop all other threads
   |          |          |             write to share variable S
   |          |          |             resume all other threads
 read S     read S      read S
   |          |          |
   |          |          |
 barrier     barrier   barrier

它运行在不同英特尔多核体系结构的3.11Linux内核之上。
如前一个问题所建议的,我正在使用一个自定义屏障来挂起/恢复我的线程。线程1到3在其无限循环的主体中多次读取共享变量S。我的问题是,如何确保它们重新启动时都读取线程4从无限循环开始时写入的最后一个值?
我想,在读写S之前,互斥锁/解锁解决方案应该可以工作,但我想知道如何避免它,因为我已经在通过suspend/resume机制对线程进行控制,确保不存在对变量的并发访问?

最佳答案

显然,您需要确保线程4中的write toS在其他线程从屏障中释放时是可见的,而不是之前。令人高兴的是,自定义屏障有一个互斥锁,当工作线程被释放时,barrier_continue()会获取并释放它。当工人重新启动时,他们将获取并释放互斥锁。因此,如果操作顺序是:
所有工作线程pthread_cond_wait()(在互斥锁下);
然后线程4获取互斥锁并写入S
线程4通过pthread_broadcast()重新启动工人;
线程4释放互斥锁;
工人们全部(重新)获取并释放互斥锁并读取S
…因为mutex的获取和释放是同步点。(实际上,3和4可以按另一个顺序完成。)
为了实现这一点,当线程4决定停止工作线程pthreads时,它需要一种方法来等待它们全部停止,这样它就可以编写S并重新启动工作线程。这是在“停止所有其他线程”之后的一个额外步骤,在这里您“等待所有其他线程停止”。这还包括锁定自定义屏障互斥锁。。。所以实际上不需要额外的锁定。
这里的问题并不是要确保重新启动后的工人可以看到S的写入,而是要确保新的S在他们停止之前不可见。您可以有一个Next_S变量,它是由工作人员在重新启动后获取的。线程4可以“停止所有其他线程”,写入Next_S,然后重新启动所有工作线程。重启后,工人可以读取Next_S,而不是之前。

关于c - 如何确保线程读取最后一个变量值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25258714/

10-11 22:09
查看更多