Not quite. You are right that it should never be called. However, the JLS/JMM can be read as not absolutely forbidding it from being called because of weaknesses in required ordering relationships among finals vs volatiles set in constructors (key is final, value is volatile), wrt the reads by threads using the entry objects. (In JMM-ese, ordering constraints for finals fall outside of the synchronizes-with relation.) That's the issue the doc comment (pasted below) refers to. No one has ever thought of any practical loophole that a processor/compiler might find to produce a null value read, and it may be provable that none exist (and perhaps someday a JLS/JMM revision will fill in gaps to clarify this), but Bill Pugh once suggested we put this in anyway just for the sake of being conservatively pedantically correct. In retrospect, I'm not so sure this was a good idea, since it leads people to come up with exotic theories.
Get 操作並沒有對底層的陣列或鍊錶產生更改操作。樓主的疑問可能是Get的時候另一個線程同時put,或者get的時候另一個線程同時remove。其實這裡沒問題的 ,如果get在前put在後,那就get到null啦,如果get後remove在前,那也會拿到null啦。不會出現put在前反而get到null的情況或是remove再前反而拿到obj的情況。因為remove或put最終的操作就是原子的設定 segment[i].table[j]. get操作沒有機會對該操作搗亂
內部實作用了鎖,你用它的時候就不需要再加一層鎖了
2/3. 寫入沒完成的時候就讀,就會讀到null,此時鎖是被寫操作lock的,等待寫入操作unlock,再去讀就可以讀到了。
get
不需要加鎖,只是讀取並不會對資料改變readValueUnderLock
正常情況不會被執行e.value
不会为null
作者Doug Lea
解釋如下在高版的jdk中
ConncurrentHashMap
已經完全重寫了,這部分程式碼也沒有了。ConncurrentHashMap 是jdk5引入的,它本身的操作就是確保了線程安全的,因此不需要加鎖了
經典讀寫模型,讀一般不用加鎖的
Get 操作並沒有對底層的陣列或鍊錶產生更改操作。樓主的疑問可能是Get的時候另一個線程同時put,或者get的時候另一個線程同時remove。其實這裡沒問題的 ,如果get在前put在後,那就get到null啦,如果get後remove在前,那也會拿到null啦。不會出現put在前反而get到null的情況或是remove再前反而拿到obj的情況。因為remove或put最終的操作就是原子的設定 segment[i].table[j]. get操作沒有機會對該操作搗亂