阿神2017-04-18 10:08:21
內部實作用了鎖,你用它的時候就不需要再加一層鎖了
『他都是复制出一个新的数组进行复制, 而非在原地操作』 你在哪里看到有复制的代码?
2/3. 寫入沒完成的時候就讀,就會讀到null,此時鎖是被寫操作lock的,等待寫入操作unlock,再去讀就可以讀到了。
阿神2017-04-18 10:08:21
get
不需要加鎖,只是讀取並不會對資料改變
readValueUnderLock
正常情況不會被執行
e.value
不会为 null
作者Doug Lea
解釋如下
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.
在高版的jdk中ConncurrentHashMap
已經完全重寫了,這部分程式碼也沒有了。
PHPz2017-04-18 10:08:21
Get 操作並沒有對底層的陣列或鍊錶產生更改操作。樓主的疑問可能是Get的時候另一個線程同時put,或者get的時候另一個線程同時remove。其實這裡沒問題的 ,如果get在前put在後,那就get到null啦,如果get後remove在前,那也會拿到null啦。不會出現put在前反而get到null的情況或是remove再前反而拿到obj的情況。因為remove或put最終的操作就是原子的設定 segment[i].table[j]. get操作沒有機會對該操作搗亂