鎖的內容很重要,首先必須明確,只有用到使用相同變量時,會發生競爭。如果線程操作的是不同實例,那麼不會發生影響。
以下代碼先構造一個抽象類CounterBase,裏面說明所有其子類必須Increment()和Decrement()兩個方法。其子類有兩個:Counter和CounterWithLock。比較有意思的是兩者都用的是Count屬性(private set),估計是可以生成默認的內部變量。前者不管鎖,直接自增自減;後者有lock,在執行Increment()時(使用到了Count),那麼該實例不能同時使用Decrement,必須等到Increment執行完纔可以。需要指出的是鎖定的是個對象object_synroot,而值類型不能作爲鎖定對象。還有,鎖定對象是唯一的、確定的。
TestCounter是通過傳入兩個類型的實例來查看結果。
static void TestCounter(CounterBase c)
{
for (int i = 0; i < 100000; i++)
{
c.Increment();
c.Decrement();
}
}
class Counter : CounterBase
{
public int Count { get; private set; } //外部無法set該屬性
public override void Increment()
{
Count++;
}
public override void Decrement()
{
Count--;
}
}
class CounterWithLock : CounterBase
{
private readonly object _syncRoot = new Object();
public int Count { get; private set; }
public override void Increment()
{
lock (_syncRoot)
{
Count++;
}
}
public override void Decrement()
{
lock (_syncRoot)
{
Count--;
}
}
}
abstract class CounterBase
{
public abstract void Increment();
public abstract void Decrement();
}
main函數:
Console.WriteLine("Incorrect counter");
var c = new Counter();
var c_1 = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c_1));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine("Total count: {0}",c.Count);
Console.WriteLine("Total count: {0}",c_1.Count);
這個實例是爲了說明如果不同實例,是不需要加鎖的。
調用含有鎖的對象:
Console.WriteLine("Correct counter");
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("Total count: {0}", c1.Count);
Console.Read();
注意這裏用的都是同一實例c1,這樣才能體現鎖的價值。