为什么这个赋值不是线程安全的?
本文关键字:线程 安全 赋值 为什么 | 更新日期: 2023-09-27 17:49:37
我一直在读Joseph Albahari写的关于线程的书:
http://www.albahari.com/threading/
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位架构上的原子操作吗?
赋值是atomic,因为任何读线程都将看到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");
…不能保证线程2会完成,因为线程2可能不会"看到"线程1的赋值。