ConcurrentHashMap学习——Unsafe类和CAS机制

CAS机制

CAS (Compare And Swap)比较并替换,CAS的三个操作数:内存地址(V)、预期值(A)、替换值(B)。
CAS操作过程:内存地址V上的值与A值相等则用B替换A值返回true,不相等返回false。
CAS指令利用JNI来完成非阻塞算法,因为java.unit.concurrent包是建立在CAS机制上的,所以相对于synchronized来说concurrent
的效率非常高。

CAS存在问题

ABA问题:CAS要判断操作值是否发生了变化,如果操作值由A变为B,又由B变为A则CAS无法判断正确。解决ABA问题的方法是加版本号,即使值由A到B再到A,两个A的版本号不同,CAS可以判断出值是否变化。

循环时间长开销大:自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。

只能保证一个共享变量的原子操作:当对一个共享变量(volatile修饰)执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,例如共享变量a和b,CAS变量a为true,CAS变量b为false但是此时a已经被替换,所以循环CAS无法保证多个共享变量的原子性,这个时候就可以用锁,或者把多个共享变量合并成一个共享变量来操作。将多个变量放到一个对象里来操作。

Unsafe类

java中CAS机制是通过sun.misc.Unsafe.compareAndSwapObject(Object var1, long var2, Object var4, Object var5)实现的。

ConcurrentHashMap中Node的CAS操作

	//tab的CAS操作
	//为什么偏移量是((long)i << ASHIFT) + ABASE
	//ABASE是tab对ConcurrentHashMap的偏移量,ASHIFT是第一个Node对tab的偏移量
	static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i, Node<K,V> c, Node<K,V> v) {
		return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
	}

	static {
		try {
			U = sun.misc.Unsafe.getUnsafe();
			Class<?> ak = Node[].class;
			ABASE = U.arrayBaseOffset(ak);
			int scale = U.arrayIndexScale(ak);
			if ((scale & (scale - 1)) != 0)
				throw new Error("data type scale not a power of two");
			ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
		} catch (Exception e) {
			throw new Error(e);
		}
	}

猜你喜欢

转载自blog.csdn.net/qq_35321596/article/details/81239963