c# - 当工作线程非竞争性地写入本地或类变量时,是否需要锁定或 volatile ?

标签 c# variables locking task volatile

对于下面的情况,当工作线程之间没有写入竞争时,是否还需要锁或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/

相关文章:

c# - Linq-To-SQL CreateDatabase 不创建存储过程

java - 重用从类返回的用户输入值,而不重新请求用户输入

oracle - Oracle 的默认对象锁超时可以更改吗?

c# - 如何在 C# 中使用字符分隔符将字符串分成两部分?

c# - 解析 HTML/CSS/PHP 文件

c# - FLURL:映射属性名称

c# - 将 C# 变量用于 cmd 字符串

javascript - 根据jquery中的元素id选择javascript变量

python - 如何在 Django 中执行表/行锁

php - MySQL表锁问题