码迷,mamicode.com
首页 > 编程语言 > 详细

CAS(Compare And Swap) 算法

时间:2020-08-02 12:45:13      阅读:36      评论:0      收藏:0      [点我收藏+]

标签:流程   oid   compare   inline   image   exception   cte   算法实现   latch   

CAS 也叫自旋锁,用来保证操作的一致性,比如用2个线程同时对一个变量累加1000,000次,得到的结果可能比2000,000少:

package juc.test.cas;

import org.junit.Test;

import java.util.concurrent.CountDownLatch;

public class NonAtomicTest {

    static long var = 0 ;
    final int totalThread = 2;
    final long timesEveryThread = 1000000;
    @Test
    public void testAtomicLong(){

        CountDownLatch cdl = new CountDownLatch(totalThread);  // thread count

        for (int j = 0; j < totalThread; j++) {
            new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i < timesEveryThread; i++) {
                        var = var + 1;
                    }
                    cdl.countDown();
                }
            }.start();
        }

        try {
            cdl.await();  // wait for all thread return
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(var);
    }
    
}

输出:

1259956

其中的原因有可能是因为他们读取的值一样,计算的结果也一样,而我们希望的结果是一个线程的操作是基于上次计算的结果,CAS可以保证,它的执行流程如图:
技术图片

值得一提的是,“比较(Compare)”和“交换(Swap)” 这两个操作需要合并为一个原子操作并加锁,也就是当有一个线程在进行cmpxchg时其他线程需要等待,防止出现2个线程同时compare发现都ok,然后都替换,比如两个线程都对i加1,i初始化为0,它们同时读取到i为0,并计算得到结果1,并且同时进行compare发现都是前值和现值都是0,很match,然后俩线程都写入1;加上一把锁,即使这俩线程同时读取到i为0,进行compare时必须有先后顺序,就可以保证操作的一致性了。

Java的原子类AtomicInteger等是利用CAS算法实现的,例程的CAS版:

package juc.test.cas;

import org.junit.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;

// See also ./hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp:93
public class AtomicTest {


    final int totalThread = 2;
    final long timesEveryThread = 1000000;
    @Test
    public void testAtomicLong(){
        AtomicLong var = new AtomicLong() ;
        CountDownLatch cdl = new CountDownLatch(totalThread);

        for (int j = 0; j < totalThread; j++) {
            new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i < timesEveryThread; i++) {
                        var.getAndIncrement();
                    }
                    cdl.countDown();
                }
            }.start();

        }

        try {
            cdl.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(var.get());
    }

}

输出:

2000000

CAS(Compare And Swap) 算法

标签:流程   oid   compare   inline   image   exception   cte   算法实现   latch   

原文地址:https://www.cnblogs.com/oaks/p/13418202.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!