ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java 乐观锁的介绍以及对compareAndSet方法的使用及理解(以AtomicBoolean为例)

2022-01-14 12:02:15  阅读:210  来源: 互联网

标签:false 为例 atomicBoolean true System println Java AtomicBoolean out


1.乐观锁是什么

乐观锁可以理解为生活中乐观的人,这种人总是想着事情会往好的方向发展。与其对应的是悲观锁,同理悲观锁对应生活中悲观的人,他们总是认为事情会往坏的方向发展。两种锁没有绝对的好坏之分。他们的好坏取决于应用场景。

正如文章开头说的那样,乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,如果没有人更新这个数据的话,就会使用原子操作去更新自己的修改,否则就不执行任何操作。这个过程可以使用两种方式实现。即版本号机制和CAS算法(compare and swap 比较与交换)。

1. 版本号机制
因为本节的重点是讲Java的乐观锁,而java的原子变量类(java.util.concurrent.atomic)是使用CAS算法实现的,所以版本号机制咱们仅作介绍,需要深入理解的可以自行查找资料哦。
版本号机制一般用于数据库,在数据库表中加一个数据版本version字段表示数据被修改的次数,当数据被修改时,version值会加一。当线程A想要更新数据值时,在读取数据的同时也会去读取version值,在提交更新时,若刚才读取的version值与当前数据库中的version值相等,则提交跟新自己的
2. CAS算法
CAS即Compare And Swap(比较与交换),是一种无锁算法,即在不使用锁的情况下实现多线程之间变量的同步,所以也叫非阻塞同步(Non- blocking Synchronization),CAS的执行过程如下图所示:

在这里插入图片描述当且仅当V的值和新值N相等时,CAS通过原子操作的方式用计算结果值A来更新V的值,否则不会执行任何操作。一般情况下是自旋操作,也就是不断的重试

3. 乐观锁的缺点

(1) ABA问题
即如果一个变量V初次读取时值是A,并且在准备赋值时检查它的值仍然是A,那能说明它的值没有被其他线程修改过吗?显然不能。因为可能在准备赋值前,V的值被其他线程修改成了其他值B,然后又修改成了A,那么CAS操作就会误认为它从来没有被修改过,这个就是CAS操作的**“ABA”问题**

(2)循环时间长开销大
自旋CAS,不成功就会一直循环执行直到成功,如果长时间不成功,会给CPU带来很大的开销

(3)只能保证一个共享变量的原子操作
CAS只对单个共享变量有效,当操作涉及到多个共享变量时CAS无效。但在JDK1.5开始,提供了AtomicReference类来保证引用对象之间的原子性,可以把多个变量放在一个对象里进行CAS操作。所以可以使用锁或者是利用AtomicReference类把多个共享变量合并成一个共享变量来操作

3.乐观锁使用场景

CAS适用于线程冲突较少的情景,一般在写操作比较少,读操作比较多的情况下推荐使用

Demo理解CompareAndSet()方法

    public static void main(String[] args) {
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
        System.out.println("=====================================");
        System.out.println("result==>"+atomicBoolean.compareAndSet(true,false));
        System.out.println("current value: " + atomicBoolean.get());//false

        System.out.println("=====================================");
        System.out.println("result1==>"+atomicBoolean.compareAndSet(true,true));
        System.out.println("current1 value: " + atomicBoolean.get());//false

        System.out.println("=====================================");
        System.out.println("result2==>"+atomicBoolean.compareAndSet(false,false));
        System.out.println("current2 value: " + atomicBoolean.get());//false

        System.out.println("=====================================");
        System.out.println("result3==>"+atomicBoolean.compareAndSet(false,true));
        System.out.println("current3 value: " + atomicBoolean.get());//true
        System.out.println("=====================================");

        System.out.println("=====================================");
        System.out.println("result4==>"+atomicBoolean.compareAndSet(true,false));
        System.out.println("current4 value: " + atomicBoolean.get());//false
        System.out.println("=====================================");

    }

需要注意的是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 {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(boolean expect, boolean update) {
        return U.compareAndSwapInt(this, VALUE,
                                   (expect ? 1 : 0),
                                   (update ? 1 : 0));
    }
 AtomicBoolean atomicBoolean
  = new AtomicBoolean(false);
atomicBoolean.compareAndSet(true,false)

这段代码,读出的初始值是false,但是第一个参数的值代表期待的值(expect),只有当这个expect值和当前从内存中读出的值相等时,才会用新值(update)去更新当前内存中的值,返回操作成功的结果为true,否则返回false,表示操作不成功。所以上面的代码会返回false,内存中现在的值不变(因为没有更新成功),还是false

 AtomicBoolean atomicBoolean
  = new AtomicBoolean(true);
atomicBoolean.compareAndSet(true,false)

再看这段代码,从内存中读出的初始值为true,expect的值也为true,此时就可以用update的值(false)更新现在内存中的值,返回true表示操作成功。所以上面这段代码会返回true,内存中的值为false,因为更新成功了

标签:false,为例,atomicBoolean,true,System,println,Java,AtomicBoolean,out
来源: https://blog.csdn.net/zxj2589/article/details/122475311

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有