为了实现多线程应用程序的无锁代码,我使用了volatile变量,
理论上讲:volatile关键字只是用来确保所有线程都看到一个volatile变量的最新值;所以如果线程A更新变量值,并且线程B在发生更新之后读取该变量,它将看到最近从线程A写入的最新值.
当我在一个Cuts 4.0中看到一个Nut shell的书
这是不正确的因为
理论上讲:volatile关键字只是用来确保所有线程都看到一个volatile变量的最新值;所以如果线程A更新变量值,并且线程B在发生更新之后读取该变量,它将看到最近从线程A写入的最新值.
当我在一个Cuts 4.0中看到一个Nut shell的书
这是不正确的因为
applying volatile doesn’t prevent a write followed by a read from being swapped.
可以通过将Thread.MemoryBarrier()放在volatile变量的每个get之前解决这个问题,如:
private volatile bool _foo = false; private void A() { //… Thread.MemoryBarrier(); if (_foo) { //do somthing } } private void B() { //… _foo = true; //… }
如果这样解决问题;考虑到我们有一个while循环,在其条件之一依赖于该值;在Thread.MemoryBarrier()之前,while循环是一个正确的方法来解决问题?例:
private void A() { Thread.MemoryBarrier(); while (_someOtherConditions && _foo) { // do somthing. } }
为了更准确,我希望_foo变量在任何线程在任何时候提供最新值;所以如果在调用变量之前插入Thread.MemoryBarrier()来修复问题,那么我可以使用Foo属性而不是_foo,并在该属性的get中执行Thread.MemoryBarrier().Like:
Foo { get { Thread.MemoryBarrier(); return _foo; } set { _foo = value; } }
解决方法
“C#在一个坚果”是正确的,但它的声明是愚蠢的.为什么?
> A’write’后跟’read’,withot’volatile’,如果它在单个线程中影响逻辑,就保证以程序顺序发生
>在多线程程序中’read’之前的’write’在你的例子中是毫无意义的.
我们来澄清一下拿你的原始代码:
private void A() { //… if (_foo) { //do something } }
如果线程调度程序已经检查了_foo变量,但是在执行某些注释之前它会被暂停呢?那么在那个时候你的其他线程可以改变_foo的值,这意味着你所有的挥发物和Thread.MemoryBarriers都没有计数!如果_foo的值为false,绝对必须避免do_something,那么您别无选择,只能使用一个锁.
然而,如果在突然_foo变为false时执行某些操作是可行的,那么这意味着volatile关键字足以满足您的需求.