gpt4 book ai didi

c# - C# 中的 Volatile 和 Thread.MemoryBarrier

转载 作者:太空狗 更新时间:2023-10-29 17:42:36 26 4
gpt4 key购买 nike

为了实现多线程应用程序的无锁代码,我使用了volatile变量,理论上:volatile关键字只是用来确保所有线程都能看到volatile变量的最新值;因此,如果线程 A 更新了变量值,而线程 B 在更新发生后立即读取该变量,它将看到最近从线程 A 写入的最新值。正如我在一本C# 4.0 in a Nutshell 书中读到的那样这是不正确因为

applying volatile doesn’t prevent a write followed by a read from being swapped.

这个问题是否可以通过在每次获取 volatile 变量之前放置 Thread.MemoryBarrier() 来解决,例如:

private volatile bool _foo = false;

private void A()
{
//…
Thread.MemoryBarrier();
if (_foo)
{
//do somthing
}
}

private void B()
{
//…
_foo = true;
//…
}

如果这解决了问题;考虑我们有一个 while 循环,它在其条件之一时依赖于该值;在 while 循环之前放置 Thread.MemoryBarrier() 是解决问题的正确方法吗?示例:

private void A()
{
Thread.MemoryBarrier();
while (_someOtherConditions && _foo)
{
// do somthing.
}
}

更准确地说,我希望 _foo 变量在任何线程随时请求它时提供它的最新值;因此,如果在调用变量之前插入 Thread.MemoryBarrier() 可以解决问题,那么我可以使用 Foo 属性而不是 _foo 并执行 Thread.MemoryBarrier() 在该属性的获取中 喜欢:

Foo
{
get
{
Thread.MemoryBarrier();
return _foo;
}
set
{
_foo = value;
}
}

最佳答案

“C# In a Nutshell”是正确的,但它的陈述没有实际意义。为什么?

  • “写入”后跟“读取”,而不是“ volatile ”,保证以程序顺序发生无论如何如果它影响单个线程中的逻辑
  • 在您的示例中,多线程程序中“读取”之前的“写入”完全没有意义

让我们澄清一下。拿你的原始代码:

private void A() 
{
//…
if (_foo)
{
//do something
}
}

如果线程调度程序已经检查了 _foo 变量,但它在 //do something 注释之前被挂起,会发生什么情况?那么,此时您的其他线程可能会更改 _foo 的值,这意味着您所有的 volatiles 和 Thread.MemoryBarriers 都没有意义!!!如果在 _foo 的值为 false 时绝对必须避免 do_something,那么您别无选择,只能使用锁。

但是,如果 do something 可以在 _foo 突然变为 false 时执行,那么这意味着 volatile 关键字足以满足您的需求。

需要明确的是:所有告诉您使用内存屏障的响应者都是不正确的,或者提供了过大的杀伤力。

关于c# - C# 中的 Volatile 和 Thread.MemoryBarrier,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4269498/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com