【问题标题】:Is Setting a Variable Atomic in THESE conditions在这些条件下设置变量原子
【发布时间】:2017-06-05 22:23:25
【问题描述】:

我有这种情况,我有一个状态变量; int 状态 = (2, 1, 0) 和一个无限循环:

ret = BoolCompareAndSwap(state, 1, 2)
if (ret) {
    // Change something ...
    state = 0;
}

这个状态设置会是原子的吗? 假设要设置一个变量,您必须:

  1. 从记忆中取出
  2. 更改值
  3. 设置新值

如果其他线程来比较变量,这将是原子的,因为实际值不会改变,直到它在内存中重新设置,对吗?

【问题讨论】:

  • 查看这个question,之前有人问过关于原子变量的问题。状态设置的顺序将取决于线程的完成方式,即使其线程安全。

标签: c multithreading variables atomic compare-and-swap


【解决方案1】:

严格来说,如果 C 编译器按位写入状态,它们仍然符合标准。写入前几位后,其他线程可以读取任何类型的垃圾。
大多数编译器都不会做这样的事情(古代 4 位处理器甚至更窄的编译器可能例外......),因为这会导致性能损失。

此外,更实际相关的是,如果任何其他线程写入(而不是仅读取)状态,如果您不保护所描述的代码免受竞争条件的影响,那么写入的值可能会丢失。

附带说明,所描述的状态更改(读取、修改、写入)绝不是原子的。然而,当非原子性易受攻击时,这个问题是有效的,这就是我在上面试图回答的问题。

更一般地说,考虑并发访问的所有可能组合是一种有效的保护机制。然而,它在许多方面都非常昂贵(设计工作、测试工作、维护期间的风险......)。
只有当这些成本总体上小于预期的节省(可能是性能)时,才可行,而不是使用适当的保护机制。

【讨论】:

  • 好吧,假设如果读取的是垃圾,CompareAndSwap 不会产生 true,并且如果它实际上是 0,其他线程只会对上述状态起作用,你能说状态变量是防止它被设置为中间值?这对我来说最有意义......(如果 A CompareAndSwap(state, 0, 2) 为真,则上述变量仅由其他线程访问)
  • 我无法想象其他线程只会在状态为 0 时做出反应。而“垃圾”表示垃圾,目的是为了最终将其设置为 0。此目标的垃圾可以通过其他有效的状态,与预期的 0 相比是垃圾,但无法与其他有效值区分开来。例如有效值 0、1、2、3。分两步清除 3,您可以在操作中间得到一个有效的非零垃圾“2”或“1”。
  • @Whiteclaws 更一般地说,考虑并发访问的所有可能组合是一种有效的保护机制。然而,它在许多方面都非常昂贵(设计工作、测试工作、维护期间的风险......)。只有当这些成本总体上小于预期的节省(可能是性能)时,才可行,而不是使用适当的保护机制。
  • 我认为只有调试才能判断这是否有效,谢谢您的精彩回答!
  • 我的荣幸。调试就像测试和测试永远不能证明没有问题,小心不要被愚弄。我有一句格言:“频繁的错误胜过罕见的错误;它们是在测试过程中发现的。因此,永远不要缩小时间窗口,将其放大或关闭。”
猜你喜欢
  • 2011-07-06
  • 2017-08-04
  • 2011-12-28
  • 2013-06-13
  • 2022-01-17
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多