`
flychao88
  • 浏览: 751866 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

深入理解并发之CompareAndSet(CAS)

 
阅读更多

一、CAS简介

CAS:Compare and Swap, 翻译成比较并交换。 

java.util.concurrent包中借助CAS实现了区别于synchronouse同步锁的一种乐观锁,使用这些类在多核CPU的机器上会有比较好的性能.

 

CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

 

今天我们主要是针对AtomicInteger的incrementAndGet做深入分析。

 

二、JAVA实现部分

 

/**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

  循环的内容是
1.取得当前值
2.计算+1后的值
3.如果当前值没有被覆盖的话设置那个+1后的值
4.如果设置没成功, 再从1开始

 

在这个方法中可以看到compareAndSet这个方法,我们进入看一下。

/**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return true if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

 调用UnSafe这个类的compareAndSwapInt

  

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

 JAVA程序也就跟踪到这里为止了,剩下的就是通过JNI调用C程序了,可是我奇怪的是为什么变量名都是var1,var2这样的命名呢?JAVA编程规范不是说不使用1,2等没有含义的字符命名吗?

 

三、JNI原生实现部分

在openJDK中找到找到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

 核心方法是compxchg,这个方法所属的类文件是在OS_CPU目录下面,由此可以看出这个类是和CPU操作有关,进入代码如下:

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_IF_MP也有锁指令实现的原子操作,其实CAS也算是有锁操作,只不过是由CPU来触发,比synchronized性能好的多。

 

分享到:
评论

相关推荐

    深入分析Java并发编程之CAS

    这些类的原子操作,如`getAndSet`、`compareAndExchange`等,都是基于`Unsafe`的CAS操作实现的。 下面是一个简单的示例,展示如何使用`Unsafe`进行CAS操作: ```java import com.walking.juc.util.UnsafeUtil; ...

    3、并发编程之CAS&Atomic原子操作详解.pdf

    - `boolean compareAndSet(int i, int expect, int update)`:如果数组中索引`i`处的值等于`expect`,则以原子方式将其设置为`update`。 3. **AtomicReference** - `V getAndSet(V newValue)`:以原子方式设置为...

    CAS原理 java 并发

    if (ref.compareAndSet(obj, new MyObject(), stamp, stamp + 1)) { System.out.println("更新成功"); } else { System.out.println("更新失败,有其他线程修改了引用或版本号"); } ``` **四、优缺点** 优点:...

    JAVA并发编程学习笔记之CAS操作

    CAS操作  CAS是单词compare and set的缩写,意思是指在set之前先比较该值有没有变化,只有在没变的情况下才对其赋值。  我们常常做这样的操作 ... if(a.compareAndSet(expect,a+1)) { doSomeThing1();

    乐观锁的一种实现方式-CAS编程开发技术共4页.pdf

    例如,`compareAndSet()`方法就是用于执行CAS操作,它的使用通常包括以下步骤: 1. 读取当前值:线程首先读取变量的当前值。 2. 拟定新值:根据当前值计算出期望的新值。 3. CAS更新:使用`compareAndSet()`尝试将...

    并发编程之一 日常学习笔记

    这些类中的方法如compareAndSet()就是实现CAS操作的关键。 CAS的优势在于它避免了锁的开销,减少了上下文切换,提高了并发性能。然而,CAS也有其局限性,比如ABA问题。如果一个值从A变为B,然后再变回A,CAS可能会...

    Java高并发编程详解.md

    有关java高并发知识总结:三种线程创建方式 深入理解Thread构造函数 Thread API #### CAS缺陷 ##### 循环时间长开销大,自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。 ##### 只能保证一个共享变量...

    并发编程以及计算机底层原理

    2. **并发锁机制**:`08-并发锁机制之深入理解synchronized(二)-fox`和`07-并发锁机制之深入理解synchronized(一)-fox`主要讲解了`synchronized`关键字。它是Java中的内置锁,用于控制对共享资源的访问,保证...

    高并发常见面试题(深入底层).docx

    - **compareAndSet**: 对象的期望值与实际值相等时,才将对象的值设置为新值。 - **ABA问题**: 如果在两次检查之间,变量的值被其他线程修改回原来值,则CAS机制无法检测到这一变化,这被称为ABA问题。 - **解决ABA...

    09、并发容器(Map、List、Set)实战及其原理

    - **无锁数据结构**:如`AtomicIntegerArray`等原子类,使用CAS(Compare and Swap)操作实现线程安全。 6. **并发容器的使用注意事项**: - 避免不必要的同步:只在必要时才使用线程安全的容器,否则可能会带来...

    深入浅出Java_Concurrency

    - `compareAndSet(int expect, int update)`:如果当前值等于预期值,则将其设置为给定的更新值,并返回`true`;否则返回`false`。 - `decrementAndGet()`:以原子方式将当前值减1。 - `get()`:获取当前值。 - ...

    Java_Concurrent_java并发工具包.pdf

    Java提供了`AtomicInteger`、`AtomicLong`等原子类,它们的原子方法如`compareAndSet`、`incrementAndGet`等,能够在不引入锁的情况下保证操作的原子性。例如,`AtomicInteger`的`addAndGet`方法,能够实现线程安全...

    Java理论与实践:非阻塞算法简介

    如果在检查旧值和尝试更新之间,有其他线程改变了变量,`compareAndSet()`会失败,从而避免了数据的不一致性。 清单1展示了使用`synchronized`关键字实现的线程安全计数器,每次`increment()`方法都会获取锁,完成...

    JAVA并发编程与高并发解决方案-并发编程四之J.U.C之AQS.docx

    为了保证线程安全,AQS提供了一个基于CAS(Compare and Set)操作的`compareAndSetTail()`方法来设置队列的`tail`节点。这一机制确保了队列的操作是原子性的,从而避免了数据竞争和不一致的问题。 综上所述,AQS...

    Java并发编程实践-03章-使用JDK并发包构建程序1

    Java提供了诸如AtomicInteger、AtomicLong、AtomicReference等原子变量类,这些类提供了基于CAS的原子操作,例如incrementAndGet()、compareAndSet()等方法,可以在不使用锁的情况下实现线程安全的更新。 **3.2.4 ...

    学习非阻塞的同步机制CAS

    }compareAndSet调用了unsafe.compareAndSwapInt,这是一个native方法,原理就是调用硬件支持的CAS方法。 CAS是一种高效的同步机制,它可以减少因为阻塞而损失的性能,提高多线程并发环境下的性能。但是,CAS操作...

    CAS简介以及CAS的缺点和处理方法

    《深入理解CAS机制及其在Java中的应用》 CAS(Compare and Swap,比较并交换)是计算机硬件层面提供的一种原子操作,常被用于并发编程中,以实现无锁数据结构。在Java中,JUC(Java Util Concurrency)库通过`java....

    Java并发编程总结——慎用CAS详解

    if (compareAndSet(current, next)) return current; } } ``` 这个方法会持续尝试自增,直到成功为止。 2. 当资源竞争非常激烈时,synchronized可能更优。因为synchronized会将线程挂起,避免了自旋造成的CPU...

    Java多线程(Synchronized+Volatile+JUC 并发工具原理+线程状态+CAS+线程池)

    CAS(Compare-And-Swap)是一种无锁机制,用于实现线程安全的更新操作。CAS 操作包括三个参数:expected value、new value 和当前值。如果当前值等于 expected value,那么就将当前值更新为 new value。 6. 线程池 ...

Global site tag (gtag.js) - Google Analytics