Heim > Fragen und Antworten > Hauptteil
阿神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操作没有机会对该操作捣乱