对于下面的情况,当工作线程之间没有写入竞争时,是否还需要锁或volatile?如果“G”不需要“Peek”访问权限,则答案有任何不同。
class A
{
Object _o; // need volatile (position A)?
Int _i; // need volatile (position B)?
Method()
{
Object o;
Int i;
Task [] task = new Task[2]
{
Task.Factory.StartNew(() => {
_o = f1(); // use lock() (position C)?
o = f2(); // use lock() (position D)?
}
Task.Factory.StartNew(() => {
_i = g1(); // use lock() (position E)?
i = g2(); // use lock() (position F)?
}
}
// "Peek" at _o, _i, o, i (position G)?
Task.WaitAll(tasks);
// Use _o, _i, o, i (position H)?
}
最佳答案
安全的做法是首先不要这样做。不要首先在一个线程上写入一个值,然后在另一个线程上读取该值。做一个Task<object>
和一个 Task<int>
将值返回给需要它们的线程,而不是创建跨线程修改变量的任务。
如果您热衷于跨线程写入变量,那么您需要保证两件事。首先,抖动不会选择会导致读取和写入及时移动的优化,其次,引入了内存屏障。内存屏障限制处理器以某些方式及时移动读取和写入。
正如 Brian Gideon 在他的回答中指出的那样,您会从 WaitAll
中获得内存障碍。 ,但我不记得这是书面保证还是只是实现细节。
正如我所说,我一开始就不会这样做。如果我被迫这样做,我至少会将我正在写入的变量标记为易变的。
关于c# - 当工作线程非竞争性地写入本地或类变量时,是否需要锁定或 volatile ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17795004/