2017-06-05 33 views
0

我有这种情况,我有一个状态变量; INT状态=(2,1,0) 和无限循环:在这些条件下设置变量原子

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

这会状态设置是原子? 假设设置一个变量,你必须:

  1. 从内存
  2. 变化值
  3. 设置新的价值

取出如果其他线程来比较变量,它会是原子的,因为直到它重新设置在内存中,实际值才会改变,是否正确?

+0

看到这个[问题](https://stackoverflow.com/questions/25319825/how-to-use-atomic-variables-in-c),这是以前问关于原子变量。状态设置的顺序取决于线程是如何完成的,即使线程安全。 – t0mm13b

回答

0

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

而且,和更实际的相关性,如果任何其他线程写入(而不是仅仅读出)状态,即写入的值可能会丢失,如果你不防范的比赛条件所描述的代码。

作为一个侧面说明,所描述的状态改变(读取,修改,写入)从来不是原子的。然而,当这种非原子性是脆弱的时候,这个问题是有效的,这正是我上面试图回答的问题。

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

+0

那么,假设CompareAndSwap不会产生真正的,如果什么是读垃圾,并且其他线程只会作用于上述状态,如果它实际上是0,你可以说状态变量被保护,它被设置为中间值?这对我来说最有意义......(如果一个CompareAndSwap(state,0,2)为true,那么上述变量只能被其他线程访问) – Whiteclaws

+0

我无法想象其他线程只会在状态为0 。“垃圾”意味着垃圾最终设置为0.此目标的垃圾可以通过其他有效状态,垃圾与预期的0相比较,但无法与其他有效值区分。例如有效值0,1,2,3。在两个步骤中清除3,您可以在操作过程中获得有效的非零垃圾“2”或“1”。 – Yunnosch

+0

@Whiteclaws更一般地说,思考所有可能的并发访问组合是一种有效的保护机制。然而,它在很多方面都非常合算(设计工作量,测试工作量,维护期间的风险......)。只有这些成本总体上小于预期的节省量(可能是性能),才能这样做,而不是采用适当的保护机制。 – Yunnosch