[Java EE] 多线程(八):CAS问题与JUC包

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:🍕 Collection与数据结构 (90平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀Java EE(94平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

1. CAS问题

1.1 什么是CAS

CAS全程compare and swap,字面意思就是比较和交换(与其说是交换,不如说是赋值),在底层会涉及到一下操作.
底层中涉及到的对象有内存和两个寄存器.

  1. 首先比较内存地址中的值和寄存器1的值是否相等.
  2. 如果相等,把寄存器2中的值赋给内存中.
  3. 如果不相等,不进行任何操作
  4. 返回值为是否赋值成功.
    注意:上述的操作为原子操作.

1.2 伪代码

注意:下面的代码不是原子的,只是用于辅助理解CAS的过程,实际的CAS问题在硬件底层中是原子的.

boolean CAS(address,expectValue,swapValue){//address内存中的值,expectValue寄存器1,swapValue寄存器2if(address == expectValue){address = swapValue;return true;}return false;
}

1.3 CAS是如何实现的

简而言之,是因为硬件方面提供了支持,软件层面才可以做到.由CPU提供了上述指令,因此操作系统内核也能够完成这样的操作,之后OS会提供出响应的api,JVM对OS提供出的api进行封装,我们便可以在Java中使用CAS.

1.4 CAS的有哪些应用

1.4.1 实现原子类

标准库中提供了java.util.concurrent.atomic 包,里面的类都是基于这种方式来实现的.
典型的就是AtomicInteger类.其中的getAndIncrement相当于i++操作.

  • 该类的构造方法可以指定一开始变量的初始值.
  • increamentAndGet --> ++i
  • getAndIncrement–> i++
  • decreamentAndGet --> --i
  • getAndDecreament --> i–
  • getAndAdd(10) --> i+=10
import java.util.concurrent.atomic.AtomicInteger;public class Demo26 {public static void main(String[] args) throws InterruptedException {AtomicInteger atomicInteger = new AtomicInteger(0);Thread thread = new Thread(()->{for (int i = 0; i < 50000; i++) {atomicInteger.incrementAndGet();}});Thread thread1 = new Thread(()->{for (int i = 0; i < 50000; i++) {atomicInteger.incrementAndGet();}});thread.start();thread1.start();thread.join();thread1.join();System.out.println(atomicInteger);}
}

运行结果:
在这里插入图片描述
伪代码实现

class AtomicIntegter{private int value;public int getAndIncrement(){int oldValue = value;while (!CAS(value,oldValue,oldValue+1)){oldValue = value;}return oldValue;}
}

总地来说,原子类没有用到任何的加锁操作(是因为CAS没有用到加锁),使得代码的效率更高,但是这种共操作只适用于部分场景,加锁的使用场景还是比原子类更加通用.

1.4.2 实现自旋锁

伪代码实现:

public class SpinLock{private Thread owner = null;public void lock(){while(!CAS(owner,null,Thread.currentThread()){//判断锁是否被占用,没有就使用当前线程赋值}}public void unlock(){this.owner = null;//解锁之后赋值为null}
}

1.5 CAS的ABA问题

1.5.1 什么是ABA问题

现在存在两个线程,t1线程和t2线程,t1线程要想进行CAS,需要进行一下操作:

  • 先读取num的值,记录到oldNum变量中.
  • 使用CAS判定当前num的值是否为A,如果为A,就修改成Z.
    如果有一个线程t2在这个中间对当前num的值进行了修改.只不过就是从A改成了B又一次改回了A.

举例说明:翻新机
这就好比你买来一个新手机,你无法判断这是一个全新的一手手机,还是有一些无良商家对二手机进行了翻新再卖给你.

1.5.2 ABA问题带来的bug

大部分情况下,ABA问题不会造成什么bug,但是不排除出现一些特殊情况会出现bug.

举例说明:钟离去银行取钱
有请助教:钟离,达达利亚

  • 正常的过程:
    t1线程希望从总结金额100中扣款50,这时候t2线程也希望如此,假设t1先进行了CAS操作,t2阻塞等待,t1线程的CAS操作把new值赋值为old-50之后,new值就变为50.之后在t2进行CAS操作的时候,t2就发现new值和old值不一样,就不会进行CAS操作.
    在这里插入图片描述
  • 异常的情况
    在钟离取款的时候,由于达达利亚考虑到钟离每次都可能不带钱,所以在钟离取款的时候,达达利亚又给钟离打了50块钱.在t1线程执行完CAS操作之后,t2还没有执行CAS,这时候进行了打款操作,t2进行CAS操作的时候,认为old值和new值相等,所以t2也进行了一次扣款操作.这时候就产生了bug.
    在这里插入图片描述

1.5.3 解决方案

要给修改的值引入版本号.版本号只加不减,每次操作一次余额之后,版本号+=1.在CAS⽐较数据当前值和旧值的同时,也要⽐较版本号是否符合预期.

  • 在CAS操作在读取旧值的时候,也要读取版本号.
  • 在真正修改的时候:
    • 如果当前版本号和读到的版本号一样的时候,修改数据.
    • 如果当前版本号高于读到的版本号的时候,就操作失败了.

继续拿前面的钟离取款的例子来说明:
在t1线程进行CAS的时候,进行了扣款操作,版本号+1,之后t3线程进行打款,对版本号+1,之后在t2线程CAS的时候,发现当前版本号高于之前读取到的版本号,则操作失败.
在这里插入图片描述

2. JUC包

JUC包,全称java.util.concurrent.其中存放了和多线程相关的组件.

2.1 Callable接口

该接口和Runnable相同,是描述一个任务的,只不过call方法有返回值,而run方法没有返回值.就是相当于给线程封装了一个返回值.
代码实例:计算1+2+3+…+1000的值

  • 不使用Callable的接口
public class Demo28 {private static int sum = 0;public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{int result = 0;for (int i = 0; i < 1000; i++) {result += i;}sum = result;});thread.start();thread.join();System.out.println(sum);}
}
  • 使用Callable接口
  1. 创建一个匿名类,实现Callable接口的call方法,方法中是累加过程,泛型参数表示返回值的类型.
  2. 把callable实例用FutureTask来包装一下,引用设置为futureTask.
  3. 创建线程,构造方法传入futureTask,启动线程.
  4. 之后通过futureTask的get方法去获取到call方法的返回值.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Demo27 {public static void main(String[] args) throws InterruptedException, ExecutionException {Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int ret = 0;for (int i = 0; i < 5000; i++) {ret++;}return ret;}};//通过匿名内部类的方法重写call方法FutureTask<Integer> futureTask = new FutureTask<>(callable);//通过FutureTask来包装callableThread thread = new Thread(futureTask);thread.start();//线程开始执行任务thread.join();System.out.println(futureTask.get());//通过futureTask的get方法;来拿到call的返回值}
}

运行结果:
在这里插入图片描述

举例说明:
有请助教:香菱,莱欧斯利
今天,莱欧斯利去万名堂吃饭,万名堂的前台招待员为莱欧斯利点好餐之后,就会产生一个菜单(call方法中的一堆东西),之后会生成小票(futureTask),小票一份值后厨联,一份是顾客联,之后后厨联的小票就会传到香菱的手中(把futureTask传给线程),香菱就会在后厨一通输出,在香菱做好之后,莱欧斯利就可以通过顾客联取到餐(get方法).
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/320438.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8个细节决定你的活动策划推广成败-华媒舍

活动策划和推广对于一个成功的活动来说至关重要。许多因素会影响活动的成功与否&#xff0c;以下我将介绍8个关键细节&#xff0c;这些细节能够决定活动的策划与推广的成败。 1. 目标定位 活动策划必须明确目标。你需要确定你的活动是为了推广何种产品或服务&#xff0c;吸引什…

简述前后端分离架构案例

Hello , 这里是小恒不会java 。今晚1点写写关于RESTful接口的使用案例&#xff0c;本文会通过django原生js前后端分离的案例简单讲解。本文带你认识一下简化版的前后端分离架构 代码 本文案例代码在GitHub上 https://github.com/lmliheng/fontend前后端分离 先说说什么是前后…

rust将json字符串直接转为map对象或者hashmap对象

有些时候我们还真的不清楚返回的json数据里面到底有哪些数据&#xff0c;数据类型是什么等&#xff0c;这个时候就可以使用批处理的方式将json字符串转为一个对象&#xff0c;然后通过这个对象的get方法来获取json里面的数据。 pub async fn test_json(&self) {let json_st…

『项目整理』易CAR通项目说明文档-我的第一款APP

『项目整理』易CAR通项目说明文档-我的第一款APP 项目介绍功能介绍技术栈介绍实现效果如何运行备注 项目介绍 易CAR通项目是我的第一个Android项目。是一款结合了AR技术的模仿懂车帝的看车软件。因为是初学&#xff0c;所示实现的效果差强人意&#xff0c;很多的功能界面只实现…

【论文阅读】Learning Texture Transformer Network for Image Super-Resolution

Learning Texture Transformer Network for Image Super-Resolution 论文地址Abstract1. 简介2.相关工作2.1单图像超分辨率2.2 Reference-based Image Super-Resolution 3. 方法3.1. Texture TransformerLearnable Texture Extractor 可学习的纹理提取器。Relevance Embedding.…

nginxconfig.io项目nginx可视化配置--搭建-视频

项目地址 https://github.com/digitalocean/nginxconfig.io搭建视频 nginxconfig.io搭建 nginxconfig.io搭建 展示效果 找到这个项目需要的docker镜像&#xff0c;有项目需要的node的版本 docker pull node:20-alpine运行这个node容器,在主机中挂载一个文件夹到容器中 主机&a…

MATLAB 变换

MATLAB 变换&#xff08;Transforms&#xff09; MATLAB提供了用于处理诸如Laplace和Fourier变换之类的变换的命令。转换在科学和工程中用作简化分析和从另一个角度查看数据的工具。 例如&#xff0c;傅立叶变换允许我们将表示为时间函数的信号转换为频率函数。拉普拉斯变换使…

微搭低代码入门03页面管理

目录 1 创建页面2 页面布局3 页面跳转总结 上一篇我们介绍了应用的基本操作&#xff0c;掌握了应用的概念后接着我们需要掌握页面的常见操作。 1 创建页面 打开应用的编辑器&#xff0c;在顶部导航条点击创建页面图标 在创建页面的时候可以从空白新建&#xff0c;也可以使用模…

screen

sLinux&#xff1a;screen命令——命令行的窗口操作_screen命令关闭窗口-CSDN博客文章浏览阅读4.2k次。功能&#xff1a;管理命令行终端切换的软件&#xff0c;常用于远程连接Linux过程中&#xff0c;同时使用多个命令行窗口。在窗口运行中的程序&#xff0c;记住窗口名字前面的…

nodejs实战——搭建websocket服务器

本博客主要介绍websocket服务器库安装&#xff0c;并举了一个简单服务器例子。 服务器端使用websocket需要安装nodejs websocket。 cd 工程目录 # 此刻我们需要执行命令&#xff1a; sudo npm init上述命令创建package.json文件&#xff0c;系统会提示相关配置。 我们也可以使…

一款开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验

Snap.Hutao 胡桃工具箱是一款以 MIT 协议开源的原神工具箱&#xff0c;专为现代化 Windows 平台设计&#xff0c;旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新功能相结合&#xff0c;提供了一套完整且实用的工具集&#xff0c;且无需依赖任何移动设…

im即时通讯源码/仿微信app源码+php即时通讯源码带红包+客服+禁言等系统php+uniapp开发

即时通讯(IM)系统是现代互联网应用中不可或缺的一部分&#xff0c;它允许用户进行实时的文本、语音、视频交流。随着技术的发展&#xff0c;IM系统的功能越来越丰富&#xff0c;如红包、客服、禁言等。本文将探讨如何使用PHP语言开发一个功能完备的即时通讯系统&#xff0c;包括…

如何让 PDF 书签从杂乱无序整洁到明丽清新

1、拉取书签&#xff08;详细步骤看文末扩展阅读&#xff09; 原状态 —— 杂乱无序 自动整理后的状态 —— 错落有致&#xff0c;但摩肩接踵 2、开始整理 全选自动整理后的书签&#xff0c;剪切 访问中英混排排版优化 - 油条工具箱 https://utils.fun/cn-en 1 粘贴 → 2 …

Linux下安装snaphu

1、官网下载安装包 2、解压&#xff0c;移动文件夹到/usr/local/下 3、在/usr/local/下创建man&#xff0c;在man下创建man1文件夹 4、进入到snaphu的src文件夹里&#xff0c;执行sudo make&#xff0c;如果报错 在这个 Makefile 中&#xff0c;-arch x86_64 是 macOS 特定的…

最近惊爆谷歌裁员

Python团队还没解散完&#xff0c;谷歌又对Flutter、Dart动手了。 什么原因呢&#xff0c;猜测啊。 谷歌裁员Python的具体原因可能是因为公司在进行技术栈的调整和优化。Python作为一种脚本语言&#xff0c;在某些情况下可能无法提供足够的性能或者扩展性&#xff0c;尤其是在…

[Unity常见小问题]打包ios后无法修改模型透明度

问题 在Editor下可以使用如下代码去修改模型的材质的透明度&#xff0c;但是打包ios后无法对透明度进行修改且没有任何warning和error using System.Collections; using System.Collections.Generic; using UnityEngine;public class NewBehaviourScript : MonoBehaviour {[R…

2010-2022年上市公司彭博ESG披露评分、分项得分数据

2010-2022年上市公司彭博ESG披露评分、分项得分数据 1、时间&#xff1a;2010-2022年 2、来源&#xff1a;Bloomberg ESG 指数 3、指标&#xff1a;股票代码、股票简称、年份、ESG披露评分、环境披露评分、社会信息披露评分、治理披露评分 4、范围&#xff1a;上市公司 5、…

RocketMQ SpringBoot 3.0不兼容解决方案

很多小伙伴在项目升级到springBoot3.0版本以上之后&#xff0c;整合很多中间件会有很多问题&#xff0c;下面带小伙伴解决springBoot3.0版本以上对于RocketMQ 不兼容问题 报错信息 *************************** APPLICATION FAILED TO START *************************** Des…

基于alpha shapes的边缘点提取(matlab)

1、原理介绍 由Edelsbrunner H提出的alpha shapes算法是一种简单、有效的快速提取边界点算法。其克服了点云边界点形状影响的缺点&#xff0c;可快速准确提取边界点。如下图所示&#xff0c;对于任意形状的平面点云&#xff0c;若一个半径为a的圆&#xff0c;绕其进行滚动&…

第五十三节 Java设计模式 - 工厂模式

Java设计模式 - 工厂模式 工厂模式是一种创建模式&#xff0c;因为此模式提供了更好的方法来创建对象。 在工厂模式中&#xff0c;我们创建对象而不将创建逻辑暴露给客户端。 例子 在以下部分中&#xff0c;我们将展示如何使用工厂模式创建对象。 由工厂模式创建的对象将是…