由于午餐时间匆忙回答而编辑..
之前代码中使用的 lock 语句锁定了在方法范围内创建的对象实例,因此它不会影响另一个调用同一方法的线程。每个线程必须能够锁定对象的同一实例,以便同步访问给定的代码块。一种方法(取决于您需要的语义)是使锁定对象成为它所使用的类的私有静态变量。这将允许给定对象的多个实例同步访问代码块或单个共享资源。如果对象的各个实例或特定于实例的资源需要同步,则应发出静态。
Volatile 不保证对给定变量的读取或写入在不同线程之间是原子的。这是一个编译器提示,用于保留指令的顺序并防止变量被缓存在寄存器中。一般来说,除非您正在处理对性能极为敏感的事情(低锁定/无锁算法、数据结构等)或者真的知道您正在做的事情,否则我会选择使用 Interlocked。在大多数应用程序中使用 volatile / interlocked / lock 之间的性能差异可以忽略不计,因此,如果您不确定最好使用能够为您提供最安全保证的方法(阅读 Joe Duffy 的博客和书籍)。
例如,在下面的示例中使用 volatile 不是线程安全的,并且递增的计数器未达到 10,000,000(当我运行测试时,它达到了 8848450)。这是因为 volatile 仅保证读取最新值(例如,不从寄存器缓存)。使用互锁时,操作是线程安全的,并且计数器确实达到 10,000,000。
public class Incrementor
{
private volatile int count;
public int Count
{
get { return count; }
}
public void UnsafeIncrement()
{
count++;
}
public void SafeIncrement()
{
Interlocked.Increment(ref count);
}
}
[TestFixture]
public class ThreadingTest
{
private const int fiveMillion = 5000000;
private const int tenMillion = 10000000;
[Test]
public void UnsafeCountShouldNotCountToTenMillion()
{
const int iterations = fiveMillion;
Incrementor incrementor = new Incrementor();
Thread thread1 = new Thread(() => UnsafeIncrement(incrementor, iterations));
Thread thread2 = new Thread(() => UnsafeIncrement(incrementor, iterations));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Assert.AreEqual(tenMillion, incrementor.Count);
}
[Test]
public void SafeIncrementShouldCountToTenMillion()
{
const int iterations = fiveMillion;
Incrementor incrementor = new Incrementor();
Thread thread1 = new Thread(() => SafeIncrement(incrementor, iterations));
Thread thread2 = new Thread(() => SafeIncrement(incrementor, iterations));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Assert.AreEqual(tenMillion, incrementor.Count);
}
private void UnsafeIncrement(Incrementor incrementor, int times)
{
for (int i =0; i < times; ++i)
incrementor.UnsafeIncrement();
}
private void SafeIncrement(Incrementor incrementor, int times)
{
for (int i = 0; i < times; ++i)
incrementor.SafeIncrement();
}
}
如果您搜索“互锁易失性”,您会找到许多问题的答案。例如,下面的一个解决了您的问题:
下面的一个简单示例显示
易失性与互锁性与锁定性