是什么

全称compare and swap,一个CPU原子指令,在硬件层面实现的机制,体现了乐观锁的思想。

JVM用C语言封装了汇编调用。Java的基础库中有很多类就是基于JNI调用C接口实现了多线程同步更新的功能。

原理

CMS有三个操作数:当前主内存变量的值V,线程本地变量预期值A,线程本地待更新值B。当需要更新变量值的时候,会先获取到内存变量值V然后很预期值A进行比较,如果相同则更新为B,如果不同,则将最新的变量值更新到预期值中再重新尝试上面的步骤,直到成功为止。

举例

以基于CAS实现的AtomicInteger 类进行讲解。

我们先写一个多线程,对同一个数据类进行分别进行加减操作10000次,正确的结果应该还是0。

没有任何多线程同步机制的代码如下:

packagepriv.nanjing.testCasClass;/** @Author : darrenqiao

**/

//多线程争用的数据类

classCounter {int count = 0;public intgetCount() {returncount;

}public void setCount(intcount) {this.count =count;

}public voidadd() {

count+= 1;

}public voiddec() {

count-= 1;

}

}//争用数据做加操作的线程

class AddDataThread extendsThread {

Counter counter;publicAddDataThread(Counter counter) {this.counter =counter;

}

@Overridepublic voidrun() {for (int i = 0; i < CasClass.LOOP; ++i) {

counter.add();

}

}

}//争用数据做减法操作的线程

class DecDataThread extendsThread {

Counter counter;publicDecDataThread(Counter counter) {this.counter =counter;

}

@Overridepublic voidrun() {for (int j = 0; j < CasClass.LOOP; j++) {

counter.dec();

}

}

}public classCasClass {final static int LOOP = 10000;public static void main(String[] args) throwsInterruptedException {

Counter counter= newCounter();

Thread addThread= newAddDataThread(counter);

Thread decThread= newDecDataThread(counter);

addThread.start();

decThread.start();

addThread.join();

decThread.join();

System.out.println(counter.getCount());

}

}

以下是三次执行结果,每一次都不一样。

为什么会出现这个结果呢?

因为 count += 1 / count -= 1 通过javap反编译Count.class文件,可以看出对应的字节码是三条指令

//count += 1

5: iconst_16: iadd7: putfield #12 //Field count:I//count 1= 1

5: iconst_16: isub7: putfield #12 //Field count:I

所以多线程切换是,可能会造成数据更新的不同步,怎么解决呢?

就是对被操作的数据加锁,可以是悲观锁,可以是乐观锁,这里使用的就是基于乐观锁实现的AtomicInteger类

packagepriv.nanjing.testCasClass;importjava.util.concurrent.atomic.AtomicInteger;/** @Author : darrenqiao

**/

//多线程争用的数据类

classCounter {//int count = 0;//使用AtomicInteger代替基本数据类型

AtomicInteger count = new AtomicInteger(0);public intgetCount() {//return count;

returncount.get();

}public voidadd() {//count += 1;

count.addAndGet(1);

}public voiddec() {//count -= 1;

count.decrementAndGet();

}

}//争用数据做加操作的线程

class AddDataThread extendsThread {

Counter counter;publicAddDataThread(Counter counter) {this.counter =counter;

}

@Overridepublic voidrun() {for (int i = 0; i < CasClass.LOOP; ++i) {

counter.add();

}

}

}//争用数据做减法操作的线程

class DecDataThread extendsThread {

Counter counter;publicDecDataThread(Counter counter) {this.counter =counter;

}

@Overridepublic voidrun() {for (int j = 0; j < CasClass.LOOP; j++) {

counter.dec();

}

}

}public classCasClass {final static int LOOP = 10000;public static void main(String[] args) throwsInterruptedException {

Counter counter= newCounter();

Thread addThread= newAddDataThread(counter);

Thread decThread= newDecDataThread(counter);

addThread.start();

decThread.start();

addThread.join();

decThread.join();

System.out.println(counter.getCount());

}

}

执行多次,会发现,结果只有一个:0.这样就保证了数据更新的原子性。

那么CAS有什么缺点需要注意?

ABA问题:我内存对象从A变成B在变成A,CAS会当成没有变化,进而去更新值,实际是有变化的。

循环时间开销大:一直和预期值不对的情况下,会一直循环。

只能保证一个共享变量的原子操作。

java 乐观锁 实例_JAVA乐观锁实现-CAS(示例代码)相关推荐

  1. java 静态初始化数据_Java 静态数据初始化的示例代码

    无论创建多少个对象,静态数据都只占用一份存储区域.static关键字不能应用于局部变量,因此它只能作用于域.如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初始值:如 ...

  2. java 数据库连接池 实例_java数据库连接池和数据库连接示例

    import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import com.mc ...

  3. java printwriter 文件,java使用PrintWriter写文件,javaprintwriter写,下面示例代码演示使用Pr...

    java使用PrintWriter写文件,javaprintwriter写,下面示例代码演示使用Pr 下面示例代码演示使用PrintWriter方法写文件. PrintWriter的构造函数接受Fil ...

  4. java乐观锁实现_Java 乐观锁原理与实战演练

    原标题:Java 乐观锁原理与实战演练 一. 前言 最近在做一个简单审批流程的项目,由于只有固定二级审批所以没有工作流组件,然后就遇到一个审批节点捞单时候,多个人同时审批时候如何保证业务正常运行的问题 ...

  5. java同步锁实例_Java lock同步锁使用实例解析

    这篇文章主要介绍了Java lock同步锁使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1)Lock是一个接口,而synchroniz ...

  6. java 线程锁概念_Java多线程——锁概念与锁优化

    为了性能与使用的场景,Java实现锁的方式有非常多.而关于锁主要的实现包含synchronized关键字.AQS框架下的锁,其中的实现都离不开以下的策略. 悲观锁与乐观锁 乐观锁.乐观的想法,认为并发 ...

  7. java锁分段_Java中锁分类

    锁的分类大致如下: 公平锁/非公平锁 可重入锁/不可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 1.公平锁/非公平锁 公平锁就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的:而非公平锁 ...

  8. java轻量级和重量级_Java 偏向锁、轻量级锁和重量级锁

    前言 最开始听到偏向锁.轻量级锁和重量级锁的概念的时候,我还以为是 Java 中提供了相应的类库来实现的,结果了解后才发现, 这三个原来是虚拟机底层对 synchronized 代码块的不同加锁方式. ...

  9. java 锁升级_Java并发 锁优化和锁升级

    前言 本篇文章介绍Java Synchronized锁优化. 锁是存在哪里的,怎么标识是什么锁 Monitor机制在Java中怎么表现的 锁优化 锁升级 1. 锁存在哪里 对象在内存中的布局分为三块区 ...

最新文章

  1. python 读取word 题库_Python-docx 读取word.docx内容
  2. oracle cast multiset table 语法演示
  3. Acess 数据库 查询数据表结构等问题小记
  4. Hanoi(汉诺)塔问题
  5. 208.实现Trie(前缀树)
  6. 状态压缩动态规划 - 总结【普及+,提高-】
  7. 微软发布Visual Studio Mac预览版
  8. Java前端如何发送date类型的参数给后端
  9. 制图折断线_cad折断线怎么画,你值得一看的技巧
  10. SIFT原作者David Lowe主页
  11. Nginx反向代理有什么用?
  12. AP AUTOSAR ——Diagnostic Management
  13. 图像频率域分析之频域谱(FDE)
  14. php中的时间戳_php时间戳是什么
  15. Leetcode小白上线第三十三天
  16. confluence服务守护脚本
  17. vue3自定义全局指令(过滤前后空格,输入框自动聚焦,点击复制内容到粘贴板)
  18. 微信小程序开发 [00] 写在前面的话,疯狂唠唠
  19. 批量打包下载阿里OSS文件
  20. ROS wiki系列|通过ROS wiki-tutorials学习节点

热门文章

  1. Python那些优雅的写法:switch-case
  2. python的22个基本语法
  3. python 并集union, 交集intersection, 差集difference, 对称差集symmetric_difference
  4. linux系统分配文件夹内存,详解Linux系统内存知识及调优方案
  5. mongodb3.2 java,MongoDB学习笔记:(3)、mongodb 3.2在java环境中的简单CRUD
  6. linux 命令读db文件格式,使用linux的db_load命令生成db数据库
  7. pytorch nn.Linear(对输入数据做线性变换:y=Ax+b)(全连接层?)
  8. 网络编程 数据的封装与解封装过程
  9. Python 中的基础语句
  10. Ubuntu16.04安装ROS时,sudo rosdep init报错,Error: cannot download default sources list from: