为什么这个赋值不是线程安全的?

时间:2014-03-12 11:34:36

标签: c# multithreading thread-safety locking

我一直在读约瑟夫·阿尔巴哈里的这本关于穿线的书:
http://www.albahari.com/threading/

在第2部分中,我找到了这个例子:
http://www.albahari.com/threading/part2.aspx#_When_to_Lock

以上是上述例子:

class ThreadUnsafe
{
  static int _x;
  static void Increment() { _x++; }
  static void Assign()    { _x = 123; }
}

线程安全版本:

class ThreadSafe
{
  static readonly object _locker = new object();
  static int _x;

  static void Increment() { lock (_locker) _x++; }
  static void Assign()    { lock (_locker) _x = 123; }
}

我无法理解为什么 Assign 方法不是线程安全的。不应该在32位和64位架构上进行整数分配是原子操作吗?

1 个答案:

答案 0 :(得分:10)

赋值是 atomic ,因为任何读取线程都会看到123或前一个值 - 而不是某个中间值。但是,在存在两个内存障碍之前,线程不能保证线程会看到新值:写入线程中的写入内存屏障,以及读取线程中的读取内存屏障。

如果您有两个这样的线程(在_x公开或内部之后,以便可以从其他类型的课程中读取 - 或者使用ThreadSafe类中的代码):< / p>

// Thread 1
Console.WriteLine("Writing thread starting");
ThreadSafe.Assign();
Console.WriteLine("Writing thread done");


// Thread 2
Console.WriteLine("Reading thread starting");
while (ThreadSafe._x != 123)
{
    // Do nothing
}
Console.WriteLine("Reading thread done");

...没有保证线程2可以完成,因为线程2可能不会&#34;看到&#34;线程1的分配。