一个 .Net Hashtable 的锁的疑惑和解决
今天同事告訴我, 鎖 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 會自動對單個寫的操作加鎖。
轉載于:https://www.cnblogs.com/hyfei0315/articles/1238627.html
總結
以上是生活随笔為你收集整理的一个 .Net Hashtable 的锁的疑惑和解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 标记语言——引用
- 下一篇: java中的日期时间的计算与比较