前言
在我们使用多线程的时候,我们会发现我们必须面临一个线程安全的问题,就是说多个线程操作同一个数据可能产生的问题是否得到解决。
对于异步线程,常常提及到锁这个概念,而我们知道锁是一个非常消耗性能的东西,而对于c# 是给我们封装了原子操作,对我们的锁进行了一些优化。在多线程的时候我们依然可以用原子操作来实现减少性能的损耗。
正文
代码如下:
static void TestCounter(CounterBase c)
{
for (int i = 0; i < 100000; i++)
{
c.increment();
c.Decrement();
}
}
abstract class CounterBase {
public abstract void increment();
public abstract void Decrement();
}
class Counter : CounterBase
{
private int _Count;
public int Count => _Count;
public override void increment()
{
//Console.WriteLine(CurrentThread.Name);
_Count++;
}
public override void Decrement()
{
//Console.WriteLine(CurrentThread.Name);
_Count--;
}
}
class CounterWithLock : CounterBase
{
private int _Count;
public int Count => _Count;
public override void increment()
{
Interlocked.Increment(ref _Count);
}
public override void Decrement()
{
Interlocked.Decrement(ref _Count);
}
}
测试:
static void Main(string[] args)
{
for (var i = 0; i < 100; i++)
{
var c = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c));
var t3 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine(c.Count);
var c1 = new CounterWithLock();
t1 = new Thread(() => TestCounter(c1));
t2 = new Thread(() => TestCounter(c1));
t3 = new Thread(() => TestCounter(c1));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine(c1.Count);
}
Console.ReadKey();
}
结论
当我们使用原子操作的时候结果就为0,这个很好的解决了我们的死锁问题,因为只有原子操作完,其他线程才可以进行操作。
原子操作的原理
后续补齐