Ale*_*lex 16 .net c# multithreading volatile
我什么时候应该使用volatile/Thread.MemoryBarrier()来保证线程安全?
Guf*_*ffa 20
您希望跨线程访问变量而不锁定时使用volatile/ Thread.MemoryBarrier().
像原子这样的变量int总是一次读写整个变量.这意味着在另一个线程更改之前,您将永远不会获得一半的值,而在更改之后,另一半则不会.因此,您可以安全地在不同的线程中读取和写入值,而无需同步.
但是,编译器可能会优化一些读取和写入,您可以使用volatile关键字来阻止这些读取和写入.例如,如果您有一个这样的循环:
sum = 0;
foreach (int value in list) {
sum += value;
}
Run Code Online (Sandbox Code Playgroud)
编译器实际上可以在处理器寄存器中进行计算,并且仅sum在循环之后将值写入变量.如果你创建sum变量volatile,编译器将生成代码,为每次更改读取和写入变量,以便它的值在整个循环中是最新的.
dtb*_*dtb 10
怎么了?
private static readonly object syncObj = new object();
private static int counter;
public static int NextValue()
{
lock (syncObj)
{
return counter++;
}
}
Run Code Online (Sandbox Code Playgroud)
?
这会为您完成所有必要的锁定,内存障碍等.它比基于volatile和的任何自定义同步代码都更好理解和更易读Thread.MemoryBarrier().
编辑
我想不出我会使用volatile或的情景Thread.MemoryBarrier().例如
private static volatile int counter;
public static int NextValue()
{
return counter++;
}
Run Code Online (Sandbox Code Playgroud)
是不是等同于上面的代码,是不是线程安全的(volatile不会使++奇迹般地成为线程安全的).
在这种情况下:
private static volatile bool done;
void Thread1()
{
while (!done)
{
// do work
}
}
void Thread2()
{
// do work
done = true;
}
Run Code Online (Sandbox Code Playgroud)
(应该可以工作)我会使用ManualResetEvent来表示Thread2何时完成.
| 归档时间: |
|
| 查看次数: |
7298 次 |
| 最近记录: |