在C中没有锁的线程之间共享布尔值

时间:2013-11-20 15:31:23

标签: c linux multithreading pthreads

我有两个线程,称它们为服务器线程和计算线程。服务器线程启动计算线程,向其传递一个指向布尔变量的指针,即“停止标志”。当服务器线程将stop标志设置为true时,计算线程应退出其计算循环并从run函数返回。

我的问题是,有没有办法在两个线程之间安全地共享该标志而不使用任何类型的锁(互斥锁,信号量等)?请记住:

  • 标志将设为真一次
  • 一旦设置为true,标志将永远不会被设置为false
  • 只有一个服务器线程,只有一个计算线程

在这种情况下,我将“安全”定义为在服务器线程中将标志设置为true的任何方法保证在合理的时间内在计算线程中反映真值。 (如果你的答案包含“最终”这个词,它可能不会满足“合理的时间”)。

我对便携式和非便携式解决方案感兴趣。我在Linux平台上运行,但除此之外还有一些灵活性:GCC,Clang,内核版本,C标准版本等。

3 个答案:

答案 0 :(得分:3)

在这种情况下,将变量定义为volatile就足够了。

只需一次写入,就无法进行损坏。

无法保证写入时间可见,但您不需要。

volatile可以防止有害的优化 - 如果编译器发现某个变量未被修改,它可能会认为它不需要从内存中重新读取它。 volatile阻止了这一点。

答案 1 :(得分:2)

将此标记(您的bool)声明为volatile就足够了。这只是禁用此变量的缓存,并保证每次读取都返回当前值。

答案 2 :(得分:1)

用于此目的的正确数据类型是新类型atomic_flag以及最近C标准C11的附带功能。大多数编译器还没有,但有类似的东西可以用来模拟这个。例如,gcc和亲属有__sync_lock_test_and_set__sync_lock_release用于同一目的。

正如其他人所建议的那样,声明变量volatile一般来说就足够了。虽然int_Bool很少见,但如果它位于缓存边界之间,则对此类变量的读取或写入可能是部分的。这可能导致变量的高阶位似乎被设置(导致解释为true)。

/* in file scope */
int work_has_been_initiated = 0;


/* inside the threads */
if (!__sync_lock_test_and_set(&work_has_been_initiated, 1)) {
   /* do the work, here */
}

如果此sematic不够强大,您可以使用其他原子操作,例如__sync_bool_compare_and_swap