C# 集合 — Hashtable 線程安全


基礎知識重要嗎?真的很重要。
就在筆者與同事聊天中突然同事提出一個問題,讓筆都有點亂了手腳(有點誇張),題目是這樣的:
問:Hashtable 是線程安全的嗎?
答:…… (沉默中,Yes Or No?Why?)
 
帶着問題我們一步一步的解答:
1、線程安全
      概念: 通俗的講就是多線程訪問時,采用了加鎖機制,當一個線程操作臨界區時,對臨界區進行保護,其他線程等前面線程操作完才能排隊操作臨界區。這樣保障數據一致減少數據污染。
2、求證
      各種資料顯示 Hashtable 的 Synchronized 靜態方法提供線程安全。那根據資料信息我們找到源代碼,找到 Synchronized 是如何提供線程安全的。
     都知道 Hashtable 來自 System.Collections 那我們就從他着手找到 Hashtable 中的靜態方法 Synchronized:
     
      從源碼中可以看出,Synchronized 返回一個 SyncHashtable 實例。我們接着找 SyncHashtable
     SyncHashtable 繼承自 Hashtable,之所以實現線程安全操作,因為 SyncHashtable 中就已經增加 lock 、
     
3、結論
    到這里至少能證明 Hashtable 在實現靜 Synchroinzed 方法時是線程安全的沒錯吧!
    下面寫個實例來說明如何使用 Synchronized 實現並發情況下,既有讀線程,又有寫線程的線程安全實例:
    
 1 private Hashtable _ht = Hashtable.Synchronized(new Hashtable());
 2         static void Main(string[] args)
 3         {
 4             new Program().TestLock();
 5             Console.WriteLine($"主線程:{Thread.CurrentThread.ManagedThreadId}");
 6             Console.ReadKey();
 7         }
 8 
 9         public void TestLock()
10         {
11             Task.Factory.StartNew(obj => SyncMethodA((string)obj), "laowang");
12             Task.Factory.StartNew(obj => SyncMethodB((string)obj), "liupangzi");
13             Thread.Sleep(6000);
14             Console.WriteLine($"輸出值:{ _ht[0]}");
15         }
16 
17 
18         private void SyncMethodA(string param)
19         {
20             Console.WriteLine($"方法A線程:{Thread.CurrentThread.ManagedThreadId}");
21             lock (_ht.SyncRoot)
22             {
23                 Thread.Sleep(5000);
24                 _ht[0] = "SyncMethodA";
25                 Console.WriteLine($"A方法輸出值:{ _ht[0]}");
26             }
27         }
28 
29         private void SyncMethodB(string param)
30         {
31             Console.WriteLine($"方法B線程:{Thread.CurrentThread.ManagedThreadId}");
32             Console.WriteLine($"B方法輸出值:{ _ht[0]}");
33             _ht[0] = "SyncMethodB";
34         }
View Code
 
     為了看到效果,線程A使用了鎖,並睡眠 5 秒,后設置 hashtable 值為 SyncMethodA ,線程B先讀取 hashtable 中的值,再寫入 SyncMethodB 值到 hashtable 中。在寫入值這句上會被 hashtable 自動銷鎖住 ,直到A釋放掉 SyncRoot 為止。
     上面代碼中我們實現鎖 SyncRoot 方式進行測試,結果:
     
    如果我們更改鎖的對象為 hashtable 實例本身,lock(_ht) ,那么線程B不會在 hashtable="SyncMethodB" 這句話自動鎖住。所以輸出值是:SyncMethodA
注:以上代碼請忽略方法傳值       
        
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM