Spring源码学习-AtomicBoolean
AtomicBoolean volatile
在阅读这个类的时候发现了几个值得注意的地方。
volatile
private volatile int value;
- 编译器优化:
使用了volatile的关键字。意在声明这个所有对这个变量操作,编译器就不会对其进行优化。 举例:
i=1;
i=2;
i=3;
编译器为了优化执行效率,会自动的默认视为一条指令,即i=3(自动跳过前面两条无用的指令);
但是加了volatile关键字,则每条指令都会得到执行,i这个变量前后被赋值3次。
注:单线程的时候,不会出现问题,但是多线程执行的时候,就会出现大问题了。
- 读值位置
cpu的处理速度跟内存的频率是相差很大的,为了减小这种差距,所以有了高频率的cpu缓存--寄存器(在cpu中)。cpu在读取数据的时候,先从内存中copy一份到寄存器中,然后从寄存器中读取。这就存在一个同步的问题。valatile的使用告诉了cpu,每次都从内存中读取值。
objectFieldOffset
valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
这个方法是使用的native方法,public native long objectFieldOffset(Field var1); 这个方法直接操作内存,告知相对地址的位置。感觉类似c++的指针,但是这个是相对位置而已,还需要再经过映射才能到实际地址。
compareAndSwapInt
3、unsafe.compareAndSwapInt(this, valueOffset, e, u)
这个方法是原子性的操作,也是调用native的方法,进行比较和交换。
在openJDK中找到了Unsafe的实现,调用的是C的封装的类。
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
UnsafeWrapper("Unsafe_CompareAndSwapInt");
oop p = JNIHandles::resolve(obj);
jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
// alternative for InterlockedCompareExchange
int mp = os::is_MP();
__asm {
mov edx, dest
mov ecx, exchange_value
mov eax, compare_value
LOCK_IF_MP(mp)
cmpxchg dword ptr [edx], ecx
}
}
到后面基本是汇编程序了,实际上这里也是使用了lock(LOCK_IF_MP)来保证。
网友评论