Hashtable的同步是個老問題了。這幾天仔細看了一下Hashtable的實現代碼,總算找到了一些答案,下面就聊聊這個。
首先說一下同步根(SyncRoot)。網上很多人都在討論說是要鎖table還是鎖它。其實,對於非同步的Hashtable,也就是普通的通過new創建的hashtable,SyncRoot就是table它本身。因為這個屬性的代碼直接的返回了this,this是誰?當然就是當前的這個hashtable了。
其實呢,如果不需要加鎖的hashtable,我們直接new出來一個hashtable然後直接用就可以了,也涉及不到所謂的SyncRoot屬性。
那需要加鎖(同步)的hashtable呢?(呵呵,不好意思,剛剛切入正題啊。),我在這裡建議用SyncHashtable的。顧名思義嘛,SyncHashtable當然就是同步hashtable啦!我看了SyncHashtable的源代碼,發現除了get方法,也就是read操作沒有加鎖之外,其他的方法都是簡單的對Hashtable的override(忘記說了,SyncHashtable是繼承Hashtable的)。也就是說,除read外的操作都是線程安全的,比如寫。那麼read操作呢?我剛開始也是心懷疑慮的,因為先前看過了ArrayList和SyncArryList的源代碼,發現SyncArrayList對所有的方法都加鎖了。但是看過hashtable的源代碼後,我的疑慮消除了。原來hashtable支持並發的read操作,如果加了鎖,那一次就只能響應一個read操作了,那樣的話效率就低很多了。不加鎖,依然線程安全的。
下面再回來繼續說一下SyncRoot。SyncHashtable也有一個SyncRoot,不過這個不是直接返回this了。其實,SyncHashtable雖然繼承自hashtable,但是它內部還有一個hashtable,然後它override了hashtable的每個方法,在裡面通過加鎖(lock的方式)的方式,對它內部的hashtable進行操作。而那個SyncRoot,返回的就是這個內部的hashtable,而不是SyncHashtable本身。這麼看起來,SyncHashtable是把它的父類當接口用了一回,呵呵。
不過呢,基本上,微軟封裝的這個SyncHashtable能夠滿足我們基本的同步hashtable的需求了。
如果你不滿足微軟提供的那個SynaHashtable,那你就得自己去寫一個同步的的hashtable了。不幸的是,微軟並沒有公開SyncHashtable,雖然我們可以通過Hashtalbe的靜態方法Synchronized來得到一個SyncHashtable,但是SyncHashtable本身是一個private class,我們不能繼承它,只能完完全全的從頭寫一個我們自己的同步hashtable了。這個時候,你是要鎖hashtable還是它的SyncRoot都沒有關系拉,因為它們就是一個東西,呵呵。