当前位置: 首页 > news >正文

AtomicInteger原理和CAS与Synchronized(juc编程)

AtomicInteger原理

4.6.1 原理介绍

AtomicInteger的本质:自旋锁 + CAS算法

CAS的全成是: Compare And Swap(比较再交换); 是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。CAS可以将read-modify-write转换为原子操作,这个原子操作

直接由处理器保证。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当旧预期值A和内存值V相同时,将内存值V修改为B并返回true,否则什么都不做,并返回false。

举例说明:

  1. 在内存值V当中,存储着值为10的变量。
    在这里插入图片描述

  2. 此时线程1想要把变量的值增加1。对线程1来说,旧的预期值 A = 10 ,要修改的新值 B = 11。

在这里插入图片描述

  1. 在线程1要提交更新之前,另一个线程2抢先一步,把内存值V中的变量值率先更新成了11。
    在这里插入图片描述

  2. 线程1开始提交更新,首先进行A和内存值V的实际值比较(Compare),发现A不等于V的值,提交失败。
    在这里插入图片描述

  3. 线程1重新获取内存值V作为当前A的值,并重新计算想要修改的新值。此时对线程1来说,A = 11,B = 12。这个重新尝试的过程被称为自旋
    在这里插入图片描述

  4. 这一次比较幸运,没有其他线程改变V的值。线程1进行Compare,发现A和V的值是相等的。
    在这里插入图片描述

  5. 线程1进行SWAP,把内存V的值替换为B,也就是12。

在这里插入图片描述

举例说明:这好比春节的时候抢火车票,下手快的会抢先买到票,而下手慢的可以再次尝试,直到买到票。

4.6.2 源码分析

那么接下来我们就来查看一下AtomicInteger类中incrementAndGet方法的源码。

public class AtomicInteger extends Number implements java.io.Serializable {// cas算法的实现类private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();// 表示变量值在内存中的偏移量地址,unsafe类就是根据内存偏移量地址获取数据值。private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");private volatile int value;// 以原子方式将当前值加1,这里返回的是自增后的值public final int incrementAndGet() {/* this表示当前AtomicInteger对象 ,1表示要增加的值 */return U.getAndAddInt(this, VALUE, 1) + 1;		// 调用Unsafe类中的getAndAddInt方法}}

UnSafe类

public final class Unsafe {// Unsafe类中的getAndAddInt方法public final int getAndAddInt(Object o, long offset, int delta) {int v;// do...while就是自旋操作,当CAS成功以后,循环结束do {// 获取AtomicInteger类中所封装的int类型的值,就相当于旧的预期值Av = getIntVolatile(o, offset); // 调用本类的weakCompareAndSetInt方法实现比较在交换; o: AtomicInteger对象, v: 相当于旧的预期值A, v + delta:新值B} while (!weakCompareAndSetInt(o, offset, v, v + delta));return v;}// Unsafe类中的weakCompareAndSetInt方法public final boolean weakCompareAndSetInt(Object o, long offset, int expected, int x) {return compareAndSetInt(o, offset, expected, x);}// 本地方法,调用CPU指令实现CASpublic final native boolean compareAndSetInt(Object o, long offset, int expected, int x);}

4.7 CAS与Synchronized

CAS和Synchronized都可以保证多线程环境下共享数据的安全性。那么他们两者有什么区别?

Synchronized是从悲观的角度出发:

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线

程阻塞,用完后再把资源转让给其它线程)。因此Synchronized我们也将其称之为悲观锁。jdk中的ReentrantLock也是一种悲观锁。

CAS是从乐观的角度出发:

总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。CAS这种机制我们也可以将其称之为乐观锁。

http://www.lryc.cn/news/377891.html

相关文章:

  • 抖音a_bogus,mstoken全参数爬虫逆向补环境2024-06-15最新版
  • 【机器学习】机器学习重要方法—— 半监督学习:理论、算法与实践
  • leetcode70 爬楼梯
  • ENVI实战—一文搞定非监督分类
  • 【Qt 学习笔记】Qt系统相关 | Qt事件 | 事件的介绍及基本概念
  • 具身智能特点及实现路线
  • 重温react-04
  • lock-锁的概念
  • Docker 可用镜像源
  • MySQL 搭建主从报错 1236
  • 华为OD机试真题2024版-求幸存数之和
  • Python - 各种计算器合集【附源码】
  • 【已解决】better-scroll在PC端如何开启鼠标滚动以及如何始终显示滚动条
  • AJAX 综合案例-day2
  • 【Esp32连接微信小程序蓝牙】附Arduino源码《 返回10007 相同特征id冲突问题》
  • 并发控制技术
  • 什么是网段
  • PHP和Mysql前后端交互效果实现
  • vue小总结
  • RapidLayout:中英文版面分析推理库
  • postman 工具下载安装使用教程_postman安装
  • 【数学建模】——【新手小白到国奖选手】——【学习路线】
  • CSS文本超限后使用省略号代替
  • 多线程下JVM内存模型 和 volatile关键字
  • Uniapp实现页面滚动Tab吸顶,点击tab内容滚动到对应tab内容位置
  • 在Elasticsearch中-SpaceJam一个全文搜索的实例
  • Microsoft Edge浏览器安装crx拓展插件教程
  • 陈晓婚前婚后大变样
  • Linux sudo -i取消密码的方法
  • PMP考试多少分才算合格通过?