多线程进阶篇Step2

2023-11-15

目录

CAS-乐观锁实现方式之一

CAS操作流程

应用1:使用CAS实现了原子类

 AtomicInteger实现i++

 实现原理:

应用2:使用CAS来实现自旋锁

应用3:CAS引发的ABA问题

问题描述

解决办法:引入版本号

synchronized锁升级流程

四个状态

无锁

偏向锁

轻量级锁

重量级锁

创建线程—Callable接口

 juc下的常用子类

1.对象锁 juc.lock

lock需要显示加锁解锁

 synchronized和lock的区别

2.Semaphore—信号量

两个核心操作:

3.CountDownLatch—大号的Join方法—计数器

 死锁

如何避免死锁


CAS-乐观锁实现方式之一

CAS全名:Compare and Swap : 比较交换

这种实现不会阻塞线程,而是不断尝试更新。

CAS操作流程

V的值代表读取到的最新主内存值,A代表当前工作内存中写入的值,B则是想要写回主内存的值

1.比较内存中的值V和当前工作内存的值A是否相等

2.若相等,可以认为当前主内存的值没有被修改,就把值B写回主内存

   若不相等,说明当前线程的值A已经过时了,不是最新的主内存值,此时需要将主内存的最新值V覆盖到A上,保存最新的工作内存,这时值B就不能写回主内存了,需要重新循环重新修改。

应用1:使用CAS实现了原子类

java.util.concurrent.atomic包中的所有类都是线程安全的原子类

i++本身是线程不安全的。

除了上锁之外,我们可以通过atomic包下的原子类来实现

 AtomicInteger实现i++

AtomicInteger count = new AtomicInteger();

这样我们可以进行 变量 的 ++ 或者 -- 操作:

 实现原理:

假如两个线程同时进行i++操作,线程1先执行了:

这是V变成了1,然后线程2执行++操作

我们会发现,线程2的A保存的是0,V!=A ,所以需要重新读取值并进行++操作。

 经过重新操作后,线程2将数据写回主内存

 如此循环往复,就会实现原子性

应用2:使用CAS来实现自旋锁

自旋锁已经说过了,就是获取锁失败的线程不是进入阻塞态,而是一种循环态,会在CPU上空转,不断查询当前锁的状态。

 也就是说只有当this.owner==null时,代表此时没有对象占用锁,就尝试加锁操作。

应用3:CAS引发的ABA问题

问题描述

ABA问题实际上就是当一个线程做了很多事,但是值最终还是没有变化时,把这个值再写会主存,这个时候另一个线程看到的值仍是自己工作内存的值,因此会直接用,但是其实不能直接用的。

假定:两个线程同时获得同一主内存值,并存放到自己的工作内存。

此时 线程1 进行一系列的运算和修改 自己线程中的值在不断变化,但最后又变回了初始值。

将值写回主存,此时主存还是那个值,线程2直接读取了。

解决办法:引入版本号

当CAS的V==A时,我们先判断版本是否正确,在进行操作。

如果不等,那也不需要判断版本了。

synchronized锁升级流程

根据竞争的激烈程度,会进行无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁的自动升级。

这里我就直接盗图了。

四个状态

无锁

没有线程开始,没人获取锁

偏向锁

当第一个线程尝试获取锁时,就把偏向锁给线程1,若是线程1再次获取锁时,没有加锁解锁过程,就验证一下锁的持有者是否是t1即可。

当第二个线程尝试获取锁JVM就会取消偏向锁的状态,升级为轻量级锁

轻量级锁

使用CAS(自旋锁)来进行轻量级锁的获取。

此状态没有获取锁的线程就一直自旋。

重量级锁

重量级锁依赖操作系统,通过mutex实现,用户态切换到内核态。

此时线程竞争非常激烈,一般这么几种情况会导致轻量级锁升级为重量级锁:

1.多个线程竞争轻量级锁(一般来说是线程数为CPU核数的一半)

2.自旋次数超过10次以上,为了避免CPU空跑,升级为重量级锁。

3.调用了Object.wait()方法,无论竞争是否激烈都升级锁,因为wait方法需要对象monitor实现,和mutex相关

创建线程—Callable接口

和Runnable最大的区别就是带返回值,并且返回值用FutureTask子类接收

同样的,我们需要Thread接收FutrueTask对象来启动线程。

FutureTask的获取call方法的返回值,调用get方法的线程会一直阻塞直到call方法执行结束,有返回值再继续执行。

 juc下的常用子类

1.对象锁 juc.lock

来自java.util.concurrent中的Lock接口也可以实现对象锁。

在JDK 1.5之后,Java语言自己实现的互斥锁实现,不需要借助操作系统的monitor机制。

lock需要显示加锁解锁

加锁:

1.死等法:

2.等会儿就算:

 解锁:

 synchronized和lock的区别

 一图流了

2.Semaphore—信号量

信号量Semaphore是一个计数器,表示当前可用资源的个数。

两个核心操作:

1.申请资源操作:

 2.释放资源操作:

 我们每次也可以尝试获取和释放多个资源:

3.CountDownLatch—大号的Join方法—计数器

CountDownLatch countDownLatch = new CountDownLatch(10);

调用await方法需要等待其他线程将计数器减为0,才能继续向下执行。很像join方法。

countDownLatch.await();

调用countDown方法使计数器 -1

countDownLatch.countDown();

以上几种工具类就是juc包的常用工具类,尤其是:

信号量—Semaphore  计数器—CountDownLatch

 死锁

举个例子:A线程在运行途中开始等待B线程唤醒自己

                 同时,B线程也在等待A线程唤醒自己

他俩谁都无法继续进行,也无法相互唤醒,全都卡在那了。

如何避免死锁

其实很简单,只要避免多个线程获取资源不要成一个循环就可以了。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程进阶篇Step2 的相关文章

随机推荐

  • java中的异常

    throw和throws的区别 相同 都是用于做异常的抛出处理的 不同点 使用的位置 throws 使用在函数上 throw使用在函数内 后面接受的内容的个数不同 throws 后跟的是异常类 可以跟多个 用逗号隔开 throws只声明异常
  • python中rsa解密_python中的RSA加密和J中的解密

    我对密码学完全陌生 我想从服务器端生成RSA密钥对并将其发送到所有客户端 浏览器 但在此之前 我只需在python中加密数据并发送到索引 html文件 并尝试用JavaScript解密 问题是当我通过random generator Ran
  • CMake 用法导览

    原文地址 http www cnblogs com coderfenghc archive 2013 01 20 2846621 html Preface 本文是CMake官方文档CMake Tutorial http www cmake
  • Unity中定时器的简易使用

    定时器写法1 float total time void Update this total time Time deltaTime if total time gt 5 5秒后停止 return 定时器写法2 void Hello thi
  • Linux部署Tomcat无法访问

    前言 环境 RedHat7 0 Tomcat7 JDK7 安装配置成功之后 启动tomcat服务 然后使用本地浏览器访问http xx xx xx xx 8080 无法访问 解决过程 首先怀疑是配置问题 终端输出 echo JAVA HOM
  • Java CSV文件读取、写入及追加工具类

    Java CSV文件读取 写入及追加工具类 追加 FileOutputStream out new FileOutputStream file true 第二个参数true代表追加 CSVUtil java import lombok ex
  • 计算机毕业设计-基于微信小程序高校学生课堂扫码考勤签到系统-校园考勤打卡签到小程序

    注意 该项目只展示部分功能 如需了解 评论区咨询即可 本文目录 1 开发环境 2 系统的设计背景 3 各角色功能模块 3 1 用户 3 2 管理员 4 系统页面展示 4 1 学生端功能模块展示 4 2 教师端功能模块展示 5 更多推荐 6
  • 【JavaScript数据结构与算法】字符串类(计算二进制子串)

    个人简介 个人主页 前端杂货铺 学习方向 主攻前端方向 也会涉及到服务端 Node js 个人状态 在校大学生一枚 已拿多个前端 offer 秋招 未来打算 为中国的工业软件事业效力 n 年 推荐学习 前端面试宝典 Vue2 Vue3 Vu
  • unity之跳一跳(完整版)

    1 场景 1 creat gt 3D objict gt plane 并重命名为ground 做为地面 如下图 2 并调整颜色 大小至适合 如下图 调正颜色 创建material project creat gt Material 用与当作
  • Prometheus热重启

    Prometheus热重启 启动prometheus时 添加参数 web enable lifecycle nohup prometheus web enable lifecycle 然后热重启 dos下执行如下命令 curl XPOST
  • JS 条件判断if语句

    1 流程控制 JS程序一般是按照书写的顺序来执行的 这种运行称为顺序运行 是程序流的默认方向 与顺序运行不同的是另一种的运行将程序流转换到脚本的另外的部分 也就是说不按照程序流运行下一条语句 而是实现别的语句 为了试这个脚本可以使用 这个控
  • mysql-workbench使用中遇到的坑

    1 mysql workbench的安装 问题 1 弹出找不到C 的库 解决 1 的确缺少了这个库 按提示下载一个就好 安装框的左下角 有下载地址 2 有这个库 但就是找不到 可能是win10的问题 win10安装msi的文件需要管理员权限
  • JVM内存JAVA_OPTS参数说明

    JAVA OPTS server Xms2048m Xmx2048m Xss512k server 一定要作为第一个参数 在多个CPU时性能佳 Xms 初始Heap大小 使用的最小内存 cpu性能高时此值应设的大一些 Xmx java he
  • 【Python3爬虫(四)】【urlib.request模块】【ssl认证+cookies(字符串类型转换、session)】

    上一篇 Python3爬虫 三 urlib request模块 cookie Request 开始线 文章目录 一 ssl认证 二 cookies 2 1 字符串类型转换 2 2 session 一 ssl认证 03 requests ss
  • 启动引导:SpringBoot的核心-自动装配(二)

    5 启动引导 SpringBoot的核心 自动装配 二 接前章 6 SpringBoot的自动装配 6 2 Import AutoConfigurationImportSelector class 根据上一章节的基础 看到这个也不难理解 它
  • 去了家新公司,技术总监不让用 IntelliJ IDEA想离职了

    最近有个小伙伴微信和我说 新去的一家公司 技术团队全部规定要用的 Eclipse 开发 技术总监不让用 IntelliJ IDEA 付费也不行 说想离职了 问我该怎么办 首先听到这件事情的时候 我表示十分理解该公司技术总监的决定 虽然我没有
  • 小米6/6X/米8/米9手机刷入鸿蒙HarmonyOS.4.0系统-刷机包下载-遥遥领先

    小米手机除了解锁root权限 刷GSI和第三方ROM也是米粉的一大爱好 这不 在华为发布了HarmonyOS 4 0系统后不久 我们小米用户也成功将自己的手机干山了HarmonyOS 4 0系统 虽然干上去HarmonyOS 4 0系统目前
  • Ubuntu16.04下使用python3,pycharm 安装django

    这里做个总结吧 一直用Ubuntu终端安装django老是安装不上去 我用的是Ubuntu16 04 里面有python2 7 和python3 5两个版本 注意 如果没有更改默认python版本的话 安装pip 直接使用 命令 sudo
  • 修改elementui的导航菜单样式,悬浮、聚焦、失焦,超方便

    最近工作中用到饿了么中的导航菜单 原悬浮背景色不符合要求 且失焦后 无背景色 文档中居然没有给修改这些的接口 急得我要去改源码了 但是吧 看了看源码我又放弃了 我觉得还不如自己重新写 这个问题放了两三天 今天又看了看 突然发现浏览器的一个小
  • 多线程进阶篇Step2

    目录 CAS 乐观锁实现方式之一 CAS操作流程 应用1 使用CAS实现了原子类 AtomicInteger实现i 实现原理 应用2 使用CAS来实现自旋锁 应用3 CAS引发的ABA问题 问题描述 解决办法 引入版本号 synchroni