zoukankan      html  css  js  c++  java
  • Java高效并发之乐观锁和悲观锁

    悲观锁:
        每次拿数据都会加锁,Synchronized属于悲观锁[一段执行逻辑加上悲观锁,不同线程同时执行时,只能有一个线程执行,其他的线程在入口处等待,直到锁被释放]
    乐观锁:
        一段执行逻辑加上乐观锁,不同线程同时执行时,可以同时进入执行,在最后更新数据的时候要检查这些数据是否被其他线程修改了(版本和执行初是否相同),没有修改则进行更新,否则放弃本次操作
        核心算法:CAS算法
            内存值、预期值、新值(首先检查某块内存的值是否跟之前我读取时的一样,如不一样则表示期间此内存值已经被别的线程更改过,舍弃本次操作,否则说明期间没有其他线程对此内存值操作,可以把新值设置给此块内存)
            如何保证CAS中的原子性:由CPU硬件指令实现[getAndIncrement中compareAndSet]

     1 public class AtomicInt {
     2             private volatile int value;
     3             public final int get() {
     4                 return value;
     5             }
     6 
     7             publicfinal int getAndIncrement() {
     8                 for (;;) {
     9                     int current = get();
    10                     int next = current + 1;
    11                     if (compareAndSet(current, next))
    12                         return current;
    13                 }
    14             }
    15 
    16             public final boolean compareAndSet(int expect, int update) {
    17                 //Unsafe类提供的硬件级别的compareAndSwapInt方法;
    18             }
    19         }

    CAS存在ABA问题:假如内存值原来是A,后来被一条线程改为B,最后又被改成了A,则CAS认为此内存值并没有发生改变,但实际上是有被其他线程改过的

    解决方法:解决的思路是引入版本号,每次变量更新都把版本号加一

    在JDK18中进行了增强[unsafe.getAndAddInt]

    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    博客园:http://www.cnblogs.com/zhuziyu/
    Copyright ©2018 不是植物
    【转载文章务必保留出处和署名,谢谢!】
  • 相关阅读:
    kali-linux镜像下载
    清除数据库所有表
    家庭医生项目进展
    2020年度发展规划的要点
    Sql Server数据类型
    window server2012R2激活
    C#介绍
    WebApi自动接口文档Swagger汉化和添加Token验证
    SQL Server 数据库内部版本号
    用户定义表类型
  • 原文地址:https://www.cnblogs.com/zhuziyu/p/8710830.html
Copyright © 2011-2022 走看看