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

Iva*_*ric 10 c# multithreading locking thread-safety

我一直在读Joseph Albahari关于线程的这本书: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; }
}
Run Code Online (Sandbox Code Playgroud)

线程安全版本:

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

  static void Increment() { lock (_locker) _x++; }
  static void Assign()    { lock (_locker) _x = 123; }
}
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么Assign方法不是线程安全的.在32位和64位架构上,整数赋值不应该是原子操作吗?

Jon*_*eet 10

赋值是原子的,因为任何读取线程都会看到123或前一个值 - 而不是某个中间值.但是,在存在两个内存障碍之前,无法保证线程将看到新值:写入线程中的写入内存屏障和读取线程中的读取内存屏障.

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

// 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");
Run Code Online (Sandbox Code Playgroud)

...不能保证线程2可以完成,因为线程2可能不会"看到"线程1中的赋值.