java 乐观锁 实例_JAVA乐观锁实现-CAS(示例代码)
是什么
全称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(示例代码)相关推荐
- java 静态初始化数据_Java 静态数据初始化的示例代码
无论创建多少个对象,静态数据都只占用一份存储区域.static关键字不能应用于局部变量,因此它只能作用于域.如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初始值:如 ...
- java 数据库连接池 实例_java数据库连接池和数据库连接示例
import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import com.mc ...
- java printwriter 文件,java使用PrintWriter写文件,javaprintwriter写,下面示例代码演示使用Pr...
java使用PrintWriter写文件,javaprintwriter写,下面示例代码演示使用Pr 下面示例代码演示使用PrintWriter方法写文件. PrintWriter的构造函数接受Fil ...
- java乐观锁实现_Java 乐观锁原理与实战演练
原标题:Java 乐观锁原理与实战演练 一. 前言 最近在做一个简单审批流程的项目,由于只有固定二级审批所以没有工作流组件,然后就遇到一个审批节点捞单时候,多个人同时审批时候如何保证业务正常运行的问题 ...
- java同步锁实例_Java lock同步锁使用实例解析
这篇文章主要介绍了Java lock同步锁使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1)Lock是一个接口,而synchroniz ...
- java 线程锁概念_Java多线程——锁概念与锁优化
为了性能与使用的场景,Java实现锁的方式有非常多.而关于锁主要的实现包含synchronized关键字.AQS框架下的锁,其中的实现都离不开以下的策略. 悲观锁与乐观锁 乐观锁.乐观的想法,认为并发 ...
- java锁分段_Java中锁分类
锁的分类大致如下: 公平锁/非公平锁 可重入锁/不可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 1.公平锁/非公平锁 公平锁就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的:而非公平锁 ...
- java轻量级和重量级_Java 偏向锁、轻量级锁和重量级锁
前言 最开始听到偏向锁.轻量级锁和重量级锁的概念的时候,我还以为是 Java 中提供了相应的类库来实现的,结果了解后才发现, 这三个原来是虚拟机底层对 synchronized 代码块的不同加锁方式. ...
- java 锁升级_Java并发 锁优化和锁升级
前言 本篇文章介绍Java Synchronized锁优化. 锁是存在哪里的,怎么标识是什么锁 Monitor机制在Java中怎么表现的 锁优化 锁升级 1. 锁存在哪里 对象在内存中的布局分为三块区 ...
最新文章
- python 读取word 题库_Python-docx 读取word.docx内容
- oracle cast multiset table 语法演示
- Acess 数据库 查询数据表结构等问题小记
- Hanoi(汉诺)塔问题
- 208.实现Trie(前缀树)
- 状态压缩动态规划 - 总结【普及+,提高-】
- 微软发布Visual Studio Mac预览版
- Java前端如何发送date类型的参数给后端
- 制图折断线_cad折断线怎么画,你值得一看的技巧
- SIFT原作者David Lowe主页
- Nginx反向代理有什么用?
- AP AUTOSAR ——Diagnostic Management
- 图像频率域分析之频域谱(FDE)
- php中的时间戳_php时间戳是什么
- Leetcode小白上线第三十三天
- confluence服务守护脚本
- vue3自定义全局指令(过滤前后空格,输入框自动聚焦,点击复制内容到粘贴板)
- 微信小程序开发 [00] 写在前面的话,疯狂唠唠
- 批量打包下载阿里OSS文件
- ROS wiki系列|通过ROS wiki-tutorials学习节点
热门文章
- Python那些优雅的写法:switch-case
- python的22个基本语法
- python 并集union, 交集intersection, 差集difference, 对称差集symmetric_difference
- linux系统分配文件夹内存,详解Linux系统内存知识及调优方案
- mongodb3.2 java,MongoDB学习笔记:(3)、mongodb 3.2在java环境中的简单CRUD
- linux 命令读db文件格式,使用linux的db_load命令生成db数据库
- pytorch nn.Linear(对输入数据做线性变换:y=Ax+b)(全连接层?)
- 网络编程 数据的封装与解封装过程
- Python 中的基础语句
- Ubuntu16.04安装ROS时,sudo rosdep init报错,Error: cannot download default sources list from: