先看一段代码
class Program
{
static void Main(string[] args)
{
var counter = new Counter();
var t1 = new Thread(() => TestCount(counter));
var t2 = new Thread(() => TestCount(counter));
var t3 = new Thread(() => TestCount(counter));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"totalCount is {counter.Count}");
var counterNoLock = new CounterNoLock();
var t4 = new Thread(() => TestCount(counterNoLock));
var t5 = new Thread(() => TestCount(counterNoLock));
var t6 = new Thread(() => TestCount(counterNoLock));
t4.Start();
t5.Start();
t6.Start();
t4.Join();
t5.Join();
t6.Join();
Console.WriteLine($"Interlocked totalCount is {counterNoLock.Count}");
Console.ReadKey();
}
static void TestCount(CounterBase model)
{
for (int i = 0; i < 10000; i++)
{
model.Increment();
model.Decrement();
}
}
}
//计数基类
abstract class CounterBase
{
public abstract void Increment();
public abstract void Decrement();
}
//计数类
class Counter : CounterBase
{
private int _count;
public int Count
{
get
{
return _count;
}
}
public override void Increment()
{
_count++;
}
public override void Decrement()
{
_count--;
}
}
//计数类
class CounterNoLock : CounterBase
{
private int _count;
public int Count
{
get
{
return _count;
}
}
public override void Increment()
{
Interlocked.Increment(ref _count);
}
public override void Decrement()
{
Interlocked.Decrement(ref _count);
}
}
结果
工作原理
运行时,创建三个对象运行TestCounter方法的代码,该方法对一个对象执行递增或递减的操作,Counter对象不是线程安全的,会遇到竞争条件,所以第一个例子的结果值是不确定的,可能为0,也可能为其他。
我们可以通过锁定对象解决这个问题,但这样会使得其他线程被阻塞,而借助于Interlocked类,无需锁定对象即可获得正确的结果,Interlocked提供了Increment,Decrement和Add等基本数学操作的源自方法,从而帮助我们再编写Counter类时无需使用锁。