前言
在我們使用多線程的時候,我們會發現我們必須面臨一個線程安全的問題,就是說多個線程操作同一個數據可能產生的問題是否得到解決。
對於異步線程,常常提及到鎖這個概念,而我們知道鎖是一個非常消耗性能的東西,而對於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,這個很好的解決了我們的死鎖問題,因為只有原子操作完,其他線程才可以進行操作。
原子操作的原理
后續補齊