美文网首页
CAS(乐观锁)

CAS(乐观锁)

作者: 皮多堡 | 来源:发表于2019-07-04 10:03 被阅读0次

    CAS乐观锁

    CAS算法即是:Compare And Swap,比较并且替换

    CAS算法存在着三个参数,内存值V,旧的预期值A,以及要更新的值B。当且仅当内存值V和预期值B相等的时候,才会将内存值修改为B,否则什么也不做,直接返回false;
    比如说某一个线程要修改某个字段的值,当这个值初始化的时候会在内存中完成,根据Java内存模型,该线程保存着这个变量的一个副本;当且仅当这个变量的副本和内存的值如果相同,那么就可以完成对值得修改,并且这个CAS操作完全是原子性的操作,也就是说此时这个操作不可能被中断

    Synchronized虽然实现了线程安全,但是在性能上不是最优的,Synchronized关键字会让没有得到锁资源的线程进入BLOCKED状态,而后在争夺到锁资源后恢复为RUNNABLE状态,这个过程中涉及到操作系统用户模式和内核模式的转换,代价比较高

    所谓原子操作类,指的是java.util.concurrent.atomic包下,一系列以Atomic开头的包装类。例如AtomicBooleanAtomicIntegerAtomicLong。它们分别用于BooleanIntegerLong类型的原子性操作。

    private static AtomicInteger count = new AtomicInteger(0);
    
        public static void main(String[] args) {
            for (int i = 0; i < 2; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(10);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        //每个线程让count自增100次
                        for (int i = 0; i < 100; i++) {
                            count.incrementAndGet();
                        }
                    }
                }).start();
            }
    
            try{
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(count);
        }
    

    使用AtomicInteger之后,最终的输出结果同样可以保证是200。并且在某些情况下,代码的性能会比Synchronized更好。


    CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

    CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。

    CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。

    更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

    import java.util.concurrent.atomic.AtomicBoolean;
    
    /**
     * @author haopeng
     */
    public class AtomicBooleanTest implements Runnable {
    
        private static AtomicBoolean flag = new AtomicBoolean(true);
    
        public static void main(String[] args) {
            AtomicBooleanTest ast = new AtomicBooleanTest();
            Thread thread1 = new Thread(ast);
            Thread thread = new Thread(ast);
            thread1.start();
            thread.start();
        }
        @Override
        public void run() {
            System.out.println("thread:"+Thread.currentThread().getName()+";flag:"+flag.get());
            if (flag.compareAndSet(true,false)){
                System.out.println(Thread.currentThread().getName()+""+flag.get());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                flag.set(true);
            }else{
                System.out.println("重试机制thread:"+Thread.currentThread().getName()+";flag:"+flag.get());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                run();
            }
    
        }
    }
    
    

    这个图中重最要的是compareAndSet(true,false)方法要拆开成compare(true)方法和Set(false)方法理解,是compare(true)是等于true后,就马上设置共享内存为false,这个时候,其它线程无论怎么走都无法走到只有得到共享内存为true时的程序隔离方法区。

    CAS的缺点:

    • 1.CPU开销较大
      在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。

    • 2.不能保证代码块的原子性
      CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用Synchronized了。

    相关文章

      网友评论

          本文标题:CAS(乐观锁)

          本文链接:https://www.haomeiwen.com/subject/btauiqtx.html