挥发性和Thread.MemoryBarrier在C# [英] Volatile and Thread.MemoryBarrier in C#
问题描述
要实施的锁定免费代码作为多线程应用程序,我用挥发性
变量,
理论上:在挥发性
关键字只是用来确保所有线程看到volatile变量的最新值;因此,如果线程 A
更新变量值和螺纹 B
读该变量只是之后更新发生会看到大多数从线程A
最近写正如我在 C#4.0果壳中的的书,
该不正确,因为读取更新后的值p>
应用挥发性并不妨碍写操作后紧跟读被调换了。
块引用>
难道这个问题正在通过把解决
Thread.MemoryBarrier()
每前获得挥发性$ C的$ C>像变量:
私人挥发性布尔_foo = FALSE;
私人无效A()
{
// ...
Thread.MemoryBarrier();
如果(_foo)
{
//做财产以后
}
}
私人无效B()
$ { b $ b // ...
_foo = TRUE;
// ...
}
和是否能解决这个问题;考虑到我们有一个while循环依赖于它的条件之一值;是把
Thread.MemoryBarrier()
前while循环是解决这一问题的正确方法?例如:私人无效A()
{
Thread.MemoryBarrier();
,而(_someOtherConditions&安培;&安培; _foo)
{
//做财产以后。
}
}
要更精确我想要的
_foo
变量给当任何线程在任何时候要求它最新鲜的价值;因此,如果插入Thread.MemoryBarrier()
之前调用变量修复了问题,那么我可以使用富
属性,而不是_foo
,并做了Thread.MemoryBarrier()
该属性一样的get内:富
{
得到
{
Thread.MemoryBarrier();
返回_foo;
}
组
{
_foo =价值;
}
}
解决方案的C#果壳中的是正确的,但它的说法是没有实际意义。为什么?
- A'写'后'读',withot'挥发',保证在节目顺序发生不管怎样的如果它影响逻辑在一个线程中的
- 在多线程程序中的读之前,'写'是的毫无意义的后顾之忧关于你的榜样。
让我们澄清一下。把你的原代码:
私人无效A()
{
// ...
如果(_foo)
{
//做些什么
}
}
如果线程调度器已经检查了
_foo
变量,但它只是取暂停前会发生什么//做一些事情
对此有何评论?那么,在这一点上你的其他线程可能会改变_foo
的值,这意味着所有的挥发物和Thread.MemoryBarriers计数什么!如果是完全有必要的do_something
避免如果_foo
的值是假的,那么你有没有选择,只能使用锁。
但是,如果它是确定的
做点什么
被执行时,突然_foo
为假,那么就意味着volatile关键字是足以满足您的需求更多。
需要明确的是:所有的谁告诉你使用一个内存屏障反应是不正确的或正在提供矫枉过正。
To implement a lock free code for multithreading application I used
volatile
variables, Theoretically: Thevolatile
keyword is simply used to make sure that all threads see the most updated value of a volatile variable; so if threadA
updates the variable value and threadB
read that variable just after that update is happened it will see the most updated value that written recently from thread A. As I read in a C# 4.0 in a Nutshell book that this is incorrect becauseapplying volatile doesn’t prevent a write followed by a read from being swapped.
Could this problem being solved by putting
Thread.MemoryBarrier()
before every get of thevolatile
variable like:private volatile bool _foo = false; private void A() { //… Thread.MemoryBarrier(); if (_foo) { //do somthing } } private void B() { //… _foo = true; //… }
And if this solves the problem; consider we have a while loop that depend on that value at one of its conditions; is putting
Thread.MemoryBarrier()
before the while loop is a correct way to fix the issue? example:private void A() { Thread.MemoryBarrier(); while (_someOtherConditions && _foo) { // do somthing. } }
To be more accurate I want the
_foo
variable to give its most fresh value when any thread asking for it at any time; so if insertingThread.MemoryBarrier()
before calling the variable fixes the issue then could I useFoo
property instead of_foo
and do aThread.MemoryBarrier()
within the get of that property Like:Foo { get { Thread.MemoryBarrier(); return _foo; } set { _foo = value; } }
解决方案The "C# In a Nutshell" is correct, but its statement is moot. Why?
- A 'write' followed by a 'read', withot 'volatile', is guaranteed to occur in program-order anyway if it effects logic within a single thread
- The 'write' before a 'read' in a multi-threaded program is utterly pointless to worry about in your example.
Let's clarify. Take your original code:
private void A() { //… if (_foo) { //do something } }
What happens if the thread scheduler has already checked the
_foo
variable, but it gets suspended just before the//do something
comment? Well, at that point your other thread could change the value of_foo
, which means that all your volatiles and Thread.MemoryBarriers counted for nothing!!! If it is absolutely essential that thedo_something
be avoided if the value of_foo
is false, then you have no choice but to use a lock.However, if it is ok for the
do something
to be executing when suddenly_foo
becomes false, then it means the volatile keyword was more than enough for your needs.To be clear: all the responders who are telling you to use a memory barrier are incorrect or are providing overkill.
这篇关于挥发性和Thread.MemoryBarrier在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!