zoukankan      html  css  js  c++  java
  • java并发编程(四)——无锁

    悲观锁与乐观锁

    悲观锁

    一种悲观的思想,总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就使用到了很多这种锁机制,比方行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再比方Java里面的同步原语synchronized关键字的实现也是悲观锁。

    乐观锁

    一种乐观的的思想,每次取数据都假设别人不会修改,所以不会上锁。当需要更新数据时,会检测这个数据是否已经被其他人更新了,如果已经被别人更新过了,就返回让用户自己选择怎么处理。乐观锁适用于读多写少的场景。

    java中解决临界区代码安全问题有两种办法:

    阻塞式方法:使用synchronized或者Lock进行加锁。这其实就是一种悲观锁的思想。

    非阻塞式方法:使用原子变量的方法。这就是一种乐观锁的思想。

    java中乐观锁是通过CAS(compare and swap)方式实现的。

    CAS算法

    CAS算法有三个操作数,内存地址V,旧值A,新值B。

    CAS算法的思想:当需要更新值时,先将旧值A与内存地址V中的值进行比较,如果相同,就说明没有其他人对这个值作更新,此时就可以执行更新操作;如果发现旧值A与内存地址V中的值不同,说明有其他人更新过这个值,此时将旧值A换成别人修改过的值,继续进行检测,直到检测到内存地址V中的值和A的值一样时,就执行更新操作。下面代码来模拟CAS算法。

    public class CAS {
    
        private int value;  //代表内存地址中的值
    
        public synchronized int compareAndSwap(int A, int B){    //java中实际上没有使用synchronized关键字,而是通过操作硬件实现的
            int oldValue = value;
            if(oldValue == A){  //如果A的值和内存地址中的值相同就进行更新
                value = B;
            }
            return oldValue;   //返回上次内存地址中的值,在更新失败时将此值赋给A
        }
    }

    CAS 有效地说明了“ 我认为位置 V 应该包含值 A;假如包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值就可。 ”这其实和乐观锁的冲突检查+数据升级的原理是一样的。

    CAS的优点:

    1、没有使用锁,不存在死锁的情况。

    2、在读多写少的情况下不需要每次都加锁,不会使其他线程阻塞。

    CAS的缺点:

    1、如果线程读写频繁,则循环检测会浪费CPU很多资源。

    2、只能保证一个共享变量的原子操作。从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,可以把多个变量放在一个对象里来进行CAS操作。

    3、存在ABA问题。

    ABA问题:

    在上面的算法中存在这样一个问题,如果线程1将A修改为B,线程2又将B修改为A,这时线程C想要修改这个值,他看到的还是A,操作可以顺利进行,但是却不知道A->B->A的这个变化。解决ABA问题可以在CAS方法中加入版本号,每次修改都使版本号加1,这样只要做了修改,版本号就会有变化。

    参考资料

    Java并发问题——乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

  • 相关阅读:
    How To Move a MySQL Data Directory to a New Location on Ubuntu 16.04
    Mysql Docker Container Command
    svg_png
    png格式图片转为svg格式图片
    Ubuntu Server如何配置SFTP(建立用户监狱)
    ubuntu用户添加adduser, useradd并给予sudo权限
    Setup FTP server on Ubuntu 14.04
    Ubuntu Server 16.04.1系统安装
    1.Linux下生成密钥
    Linux查看设备命令
  • 原文地址:https://www.cnblogs.com/Zz-feng/p/13209229.html
Copyright © 2011-2022 走看看