Java里的CompareAndSet(CAS)ITeye - 牛牛娱乐

Java里的CompareAndSet(CAS)ITeye

2019年02月18日11时49分32秒 | 作者: 语梦 | 标签: 办法,调用,开端 | 浏览: 199

Atomic 从JDK5开端, java.util.concurrent包里供给了许多面向并发编程的类. 运用这些类在多核CPU的机器上会有比较好的功能.
首要原因是这些类里边大多运用(失利-重试办法的)达观锁而不是synchronized办法的失望锁.

今日有时刻盯梢了一下AtomicInteger的incrementAndGet的完成.
自己对并发编程也不是特别了解, 在这儿就是做个笔记, 便利今后再深入研究.

1. incrementAndGet的完成
    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }
首要能够看到他是经过一个无限循环(spin)直到increment成功停止.  
循环的内容是
1.获得当时值
2.核算+1后的值
3.假如当时值还有用(没有被)的话设置那个+1后的值
4.假如设置没成功(当时值现已无效了即被其他线程改过了), 再从1开端.

2. compareAndSet的完成
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
直接调用的是UnSafe这个类的compareAndSwapInt办法
全称是sun.misc.Unsafe. 这个类是Oracle(Sun)供给的完成. 能够在其他公司的JDK里就不是这个类了

3. compareAndSwapInt的完成
    /**
     * Atomically update Java variable to  tt x /tt  if it is currently
     * holding  tt expected /tt .
     * @return  tt true /tt  if successful
     */
    public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);
能够看到, 不是用Java完成的, 而是经过JNI调用操作系统的原生程序.

4. compareAndSwapInt的native完成
假如你下载了OpenJDK的源代码的话在hotspot\src\share\vm\prims\目录下能够找到unsafe.cpp
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
能够看到实际上调用Atomic类的cmpxchg办法.

5. Atomic的cmpxchg
这个类的完成是跟操作系统有关, 跟CPU架构也有关, 假如是windows下x86的架构
完成在hotspot\src\os_cpu\windows_x86\vm\目录的atomic_windows_x86.inline.hpp文件里
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
  }
}
在这儿能够看到是用嵌入的汇编完成的, 要害CPU指令是 cmpxchg
到这儿无法再往下找代码了. 也就是说CAS的原子性实际上是CPU完成的. 其实在这一点上仍是有排他锁的. 仅仅比重用synchronized, 这儿的排他时刻要短的多. 所以在多线程情况下功能会比较好.

代码里有个alternative for InterlockedCompareExchange
这个InterlockedCompareExchange是WINAPI里的一个函数, 做的工作和上面这段汇编是相同的
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683560%28v=vs.85%29.aspx

6. 最终再贴一下x86的cmpxchg指定
Opcode CMPXCHG
CPU: I486+ 
Type of Instruction: User 

Instruction: CMPXCHG dest, src 

Description: Compares the accumulator with dest. If equal the "dest" 
is loaded with "src", otherwise the accumulator is loaded 
with "dest". 

Flags Affected: AF, CF, OF, PF, SF, ZF 

CPU mode: RM,PM,VM,SMM 
+++++++++++++++++++++++ 
Clocks: 
CMPXCHG reg, reg 6 
CMPXCHG mem, reg 7 (10 if compartion fails) 


  发表于 2013-04-24 17:20 黑灵 阅览(1404) 谈论(0)  修改  保藏
版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表牛牛娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章