62,614
社区成员
发帖
与我相关
我的任务
分享
V get(Object key, int hash) {
if (count != 0) { // read-volatile
HashEntry<K,V> e = getFirst(hash);
while (e != null) {
if (e.hash == hash && key.equals(e.key)) {
V v = e.value;
if (v != null)
return v;
return readValueUnderLock(e); // recheck
}
e = e.next;
}
}
return null;
}
V put(K key, int hash, V value, boolean onlyIfAbsent) {
lock();
try {
int c = count;
if (c++ > threshold) // ensure capacity
rehash();
HashEntry<K,V>[] tab = table;
int index = hash & (tab.length - 1);
HashEntry<K,V> first = tab[index];
HashEntry<K,V> e = first;
while (e != null && (e.hash != hash || !key.equals(e.key)))
e = e.next;
V oldValue;
if (e != null) {
oldValue = e.value;
if (!onlyIfAbsent)
e.value = value;
}
else {
oldValue = null;
++modCount;
tab[index] = new HashEntry<K,V>(key, hash, first, value);
count = c; // write-volatile
}
return oldValue;
} finally {
unlock();
}
}
4. Happens-before法则:(Java 内存模型)
如果动作B要看到动作A的执行结果(无论A/B是否在同一个线程里面执行),那么A/B就需要满足happens-before关系。
Happens-before的几个规则:
•Program order rule:同一个线程中的每个Action都happens-before于出现在其后的任何一个Action。
•Monitor lock rule:对一个监视器的解锁happens-before于每一个后续对同一个监视器的加锁。
•Volatile variable rule:对volatile字段的写入操作happens-before于每一个后续的同一个字段的读操作。
•Thread start rule:Thread.start()的调用会happens-before于启动线程里面的动作。
•Thread termination rule:Thread中的所有动作都happens-before于其他线程检查到此线程结束或者Thread.join()中返回或者Thread.isAlive()==false。
•Interruption rule:一个线程A调用另一个另一个线程B的interrupt()都happens-before于线程A发现B被A中断(B抛出异常或者A检测到B的isInterrupted()或者interrupted())。
•Finalizer rule:一个对象构造函数的结束happens-before与该对象的finalizer的开始
•Transitivity:如果A动作happens-before于B动作,而B动作happens-before与C动作,那么A动作happens-before于C动作。
因为CPU是可以不按我们写代码的顺序执行内存的存取过程的,也就是指令会乱序或并行运行, 只有上面的happens-before所规定的情况下,才保证顺序性。
V get(Object key, int hash) {
if (count != 0) { // read-volatile
HashEntry<K,V> e = getFirst(hash);
while (e != null) {
if (e.hash == hash && key.equals(e.key)) {
V v = e.value;
if (v != null)
return v;
return readValueUnderLock(e); // recheck
}
e = e.next;
}
}
return null;
}
V put(K key, int hash, V value, boolean onlyIfAbsent) {
lock();
try {
int c = count;
if (c++ > threshold) // ensure capacity
rehash();
HashEntry<K,V>[] tab = table;
int index = hash & (tab.length - 1);
HashEntry<K,V> first = tab[index];
HashEntry<K,V> e = first;
while (e != null && (e.hash != hash || !key.equals(e.key)))
e = e.next;
V oldValue;
1. if (e != null) { //在这一句的时候A线程挂起 B线程执行,会找到元素并直接返回
2. oldValue = e.value; //旧值被更新
if (!onlyIfAbsent)
e.value = value;
}
else {
oldValue = null;
++modCount;
tab[index] = new HashEntry<K,V>(key, hash, first, value);
count = c; // write-volatile
}
return oldValue;
} finally {
unlock();
}
}
import java.util.concurrent.ConcurrentHashMap;
public class Test2 extends Thread{
static ConcurrentHashMap<String, String> chm = new ConcurrentHashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
chm.put("one", "one");
new Test2().start();
Thread.sleep(200);
chm.put("one", "TTTT");
System.out.println(chm.get("one"));
Thread.sleep(1000);
System.out.println(chm.get("one"));
}
public void run(){
try {
System.out.println("thread2 changing!");
Thread.sleep(1000);
chm.put("one", "two");
System.out.println("thread2 change over");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}