【C#】41. 線程中使用lock

鎖的內容很重要,首先必須明確,只有用到使用相同變量時,會發生競爭。如果線程操作的是不同實例,那麼不會發生影響。

以下代碼先構造一個抽象類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,這樣才能體現鎖的價值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章