linux c线程共享,关于linux:在C之间不带锁的情况下共享线程之间的布尔值

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

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

标志将一次设置为true

一旦设置为true,标志将永远不会重新设置为false

只有一个服务器线程,只有一个计算线程

在这种情况下,我将"安全"定义为可以确保在合理的时间内在服务器线程中将标志设置为true的任何方法,以在计算线程中反映出true值。 (如果您的答案包含"最终"一词,则可能不满足"合理的时间")。

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

合理的时间量取决于计算循环的内容。

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

只需一次写入,就不可能损坏。

无法保证写入内容可见的时间,但是您不需要这样做。

volatile防止有害的优化-如果编译器发现未修改变量,则可能会认为它不需要从内存中重新读取它。 volatile防止这种情况。

不,您还必须向编译器说明必须将变量备份到内存中。

@JensGustedt,volatile执行此操作。

我看不到volatile在哪里执行此操作。 register和volatile绝不矛盾,并且编译器有权不备份内存中的易失性变量。 volatile禁止的唯一事情是有关变量值的某些假设。

@JensGustedt,volatile禁止有关如何修改变量的假设(请参阅C99 6.7.3-6)。如果不使用内存备份它导致另一个线程的写操作不起作用,则它必须使用内存备份它。如果它能以某种方式将其保存在寄存器中,同时确保来自另一个线程的写入确实生效-则没有问题。

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

为此目的,正确的数据类型是新的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 */

}

如果此语义不足以实现您的目的,则可以使用其他原子操作,例如__sync_bool_compare_and_swap。

您能否举一个使用__sync_lock_test_and_set和__sync_lock_release的示例?

这是一个过大的杀伤力-如果只有一个线程修改该标志,则不需要原子操作。尽管我承认有时矫over过正会更好,但是万一代码变得更加复杂而又没人愿意更新同步。

@ugoren,不,这不是矫kill过正。在大多数体系结构上,这将导致非常简单的汇编代码,但是有些体系结构需要特别注意这些事项。知道是什么情况并生成适当的代码是编译器作者的工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值