SyncRoot 屬性應用

鎖 hashtable 應該鎖它的 SyncRoot 屬性而不應該鎖它的實例, 例如:

Hashtable ht = new Hashtable();
lock(ht.SyncRoot)
{
...
}

看了 .Net Framework 文檔, 給的例子也是鎖 SyncRoot 屬性, 說如果鎖實例的話不能保證在併發情況下的同步, 我很疑惑, 爲什麼不能鎖 hashtable 實例本身呢?

做了個實驗, 兩個線程 A 和 B, 用鎖實例和鎖 SyncRoot 兩種方式測試, 都沒有問題, 結果是一樣的。

後來, 用 Hashtable.Synchronized 創建自動線程同步的 hashtable, 終於明白了 SyncRoot 的作用。先說說自動線程同步的 Hashtable: 如果 Hashtable 要允許併發讀但只能一個線程寫, 要這麼創建 Hashtable 實例:

Hashtable hashtable = Hashtable.Synchronized(new Hashtable());

這樣, 如果有多個線程併發的企圖寫 hashtable 裏面的 item, 則同一時刻只能有一個線程寫, 其餘阻塞; 對讀的線程則不受影響。

測試的代碼是這樣的:

Hashtable _hashtable = Hashtable.Synchronized(new Hashtable());

public void TestLock()
{
Thread t1 = new Thread(new ThreadStart(SyncFunctionA));
Thread t2 = new Thread(new ThreadStart(SyncFunctionB));

t1.Start();
t2.Start();

Thread.Sleep(8000);

Console.WriteLine("hashtable[" + _key_a + "] = " + _hashtable[_key_a]);
}

private void SyncFunctionA()
{
lock (_hashtable.SyncRoot)
{
Thread.Sleep(5000);
_hashtable[_key_a] = "Value set by SyncFunctionA";
}
}

private void SyncFunctionB()
{
Console.WriteLine("hashtable[" + _key_a + "] = " + _hashtable[_key_a]);
_hashtable[_key_a] = "Value set by SyncFunctionB";

}

爲了清楚的看到效果, 線程 A 用了鎖, 並睡眠 5 秒, 睡醒後設置一下 hashtable 裏的 item. 線程 B 先讀一下 hashtable 裏的 item, 再寫 hashtable 裏的 item。因爲對 SyncRoot 加了鎖, 即使線程 B 沒有顯式的對 hashtable 加鎖, 但在 _hashtable[_key_a] = "Value set by SyncFunctionB" 一句上也會被 hashtable 自動鎖住, 直到線程 A 釋放掉 SyncRoot 鎖爲止。如果線程 A 不是鎖 SyncRoot 而是鎖 hashtable 實例本身, 那麼線程 B 不會在 _hashtable[_key_a] = "Value set by SyncFunctionB" 上被自動鎖住。

所以, 總結如下:

如果想鎖整個 hashtable, 包括讀和寫, 即不允許併發的讀和寫, 那應該鎖 hashtable 實例;
如果想允許併發的讀, 不允許併發的寫, 那應該創建 Synchronized 的 hashtable, 並對要加鎖的一塊代碼用 SyncRoot 鎖住, 如果不需要對一塊代碼加鎖, 則 hashtable 會自動對單個寫的操作加鎖。

參考自:http://blog.csdn.net/seamonkey/article/details/583613

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