線程安全就是多線程訪問時(WEB網頁多用戶訪問一個頁面時),采用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程才可使用。不會出現數據不一致或者數據污染。
Hashtable 表示鍵/值對的集合,這些鍵/值對根據鍵的哈希代碼進行組織,它的Key不能為null,Value可以為null,這一點與Hashmap不同(本身不是線程安全的),對於Hashtable它是實現了IDictionary和ICollection接口的,它的key與value都是object類型的,不支持泛型,進行類型轉換成需要裝箱與拆箱(boxing,unboxing),這在性能肯定會有一些影響,所以,微軟這邊給出了支持泛型的鍵值對集合Dictionary,而Dictionary本身也不是線程安全的,我們需要對它加鎖(lock),才能避免多線程環境下產生的一些錯誤。
下面我們來看一下線程安全的Hashtable代碼片斷:
Hashtable ht = Hashtable.Synchronized(new Hashtable()); ht.Add("ok", null); Console.WriteLine(ht["ok"]);
我們在來看一下Dictionary對象,可以使它基類提供的SyncRoot屬性,來實現它內部對象的線程安全
Dictionary<string, string> dic = new Dictionary<string, string>(); lock ((dic as ICollection).SyncRoot) { dic.Add("ok", "ok value"); }
下面我們來做一個實例,還是Dictionary的線程安全問題,我們有兩個線程,t1和t2,當我們為它加lock之后,t1純種在進行dic.Ad操作時,t2並不能進行訪問
當t1完成add操作后,t2線程才進行執行,這時它就可以改變dic 元素的值了,程序運行正常,但如果沒有lock鎖機制,t1與 t2線程誰先執行就不確定了,這時,
如果t1先執行,當然沒有問題,但如果t2先操作了,程序出現異常,因為dic元素沒有被add,所以無法改變其值。
看代碼:
Dictionary<string, string> dic = new Dictionary<string, string>(); Thread t1 = new Thread(() => { lock ((dic as ICollection).SyncRoot) //dic對象被保存,處於臨界區 { dic.Add("ok1", "ok value1");//這句先向字典添加 } }); Thread t2 = new Thread(() => { lock ((dic as ICollection).SyncRoot) { dic["ok1"] = "ok value2"; } }); t1.Start(); t2.Start(); Thread.Sleep(2000);
而對於Hashtable來說,如果希望對它進行寫加鎖,讀不加鎖,也可以通過lock在代碼段時去實現
Thread t1 = new Thread(() => { lock (ht.SyncRoot) { ht.Add(i, i); } });
OK,對於hashtable的線程安全這塊就說到這里,最后和大家說一下,咱們做WEB開發的工程師們,一定要注意線程安全這塊的知識,因為你寫的程序,肯定是處
於多線程環境下的,呵呵。