线程不安全
lock进行线程锁定
public abstract class CounterBase {
public abstract void Increase();
public abstract void Decrease();
}
public class Counter : CounterBase
{
public int Count { get; private set; }
public override void Decrease()
{
Count--;
}
public override void Increase()
{
Count++;
}
}
public class CounterWithLock : CounterBase
{
private readonly object _syncRoot = new Object();
public int Count { get; private set; }
public override void Decrease()
{
lock (_syncRoot)
{
Count--;
}
}
public override void Increase()
{
lock (_syncRoot)
{
Count++;
}
}
}
测试
const int printNum = 1000000;
static void Main(string[] args)
{
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("total count:{0}", 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();
t3.Join();
Console.WriteLine("total count:{0}", c1.Count);
Console.ReadLine();
}
static void TestCounter(CounterBase c)
{
for(int i = 0; i < printNum; i++)
{
c.Increase();
c.Decrease();
}
}
输出
total count:36312
total count:0
分析:
不使用Lock的方法中,不同线程调用时会造成类似数据库的脏读,大家都会读取这个count值
使用Lock时,可以保证只有当前线程读取,其他线程等待,不会出现值不一样的情况。