《Java并发编程实战》课程笔记(十四)

news/2024/11/24 1:34:34/

原子类:无锁工具类的典范

  • 对于简单的原子性问题,还有一种无锁方案。Java SDK 并发包将这种无锁方案封装提炼之后,实现了一系列的原子类。
  • 无锁方案相对互斥锁方案,最大的好处就是性能。
    • 互斥锁方案为了保证互斥性,需要执行加锁、解锁操作,而加锁、解锁操作本身就消耗性能;同时拿不到锁的线程还会进入阻塞状态,进而触发线程切换,线程切换对性能的消耗也很大。
    • 相比之下,无锁方案则完全没有加锁、解锁的性能消耗,同时还能保证互斥性,既解决了问题,又没有带来新的问题,可谓绝佳方案。

无锁方案的实现原理

  • 其实原子类性能高的秘密很简单,硬件支持而已。
    • CPU 为了解决并发问题,提供了 CAS 指令(CAS,全称是 Compare And Swap,即“比较并交换”)。
    • CAS 指令包含 3 个参数:共享变量的内存地址 A、用于比较的值 B 和共享变量的新值 C;
    • 并且只有当内存中地址 A 处的值等于 B 时,才能将内存中地址 A 处的值更新为新值 C。
    • 作为⼀条 CPU 指令,CAS 指令本身是能够保证原子性的。
  • 使用 CAS 来解决并发问题,⼀般都会伴随着自旋,而所谓自旋,其实就是循环尝试。

看 Java 如何实现原子化的 count += 1

  • 在 Java 1.8 版本中,getAndIncrement() 方法会转调 unsafe.getAndAddLong() 方法。这里 this 和 valueOffset 两个参数可以唯一确定共享变量的内存地址。
    final long getAndIncrement() {return unsafe.getAndAddLong(this, valueOffset, 1L);
    }
    
    • unsafe.getAndAddLong() 方法首先会在内存中读取共享变量的值,之后循环调用 compareAndSwapLong() 方法来尝试设置共享变量的值,直到成功为止。
    • compareAndSwapLong() 是⼀个 native 方法,只有当内存中共享变量的值等于 expected 时,才会将共享变量的值更新为 x,并且返回 true;否则返回 fasle。
    • compareAndSwapLong 的语义和 CAS 指令的语义的差别仅仅是返回值不同而已。
  • Java 提供的原子类里面 CAS 一般被实现为 compareAndSet(),compareAndSet() 的语义和 CAS 指令的语义的差别仅仅是返回值不同而已,compareAndSet() 里面如果更新成功,则会返回 true,否则返回 false。

原子类概览

在这里插入图片描述

  • 原子化的基本数据类型
    • 相关实现有 AtomicBoolean、AtomicInteger 和 AtomicLong。
  • 原子化的对象引用类型
    • 相关实现有 AtomicReference、AtomicStampedReference 和 AtomicMarkableReference,利用它们可以实现对象引用的原子化更新。
    • 对象引用的更新需要重点关注 ABA 问题,AtomicStampedReference 和 AtomicMarkableReference 这两个原子类可以解决 ABA 问题。
    • 解决 ABA 问题的思路其实很简单,增加一个版本号维度就可以了,每次执行 CAS 操作,附加再更新一个版本号,只要保证版本号是递增的,那么即便 A 变成 B 之后再变回 A,版本号也不会变回来(版本号递增的)。
  • 原子化数组
    • 相关实现有 AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray,利用这些原子类,我们可以原子化地更新数组里面的每一个元素。
    • 这些类提供的方法和原子化的基本数据类型的区别仅仅是:每个方法多了一个数组的索引参数。
  • 原子化对象属性更新器
    • 相关实现有 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和
      AtomicReferenceFieldUpdater,利用它们可以原子化地更新对象的属性,这三个方法都是利用反射机制实现的。
    • 对象属性必须是 volatile 类型的,只有这样才能保证可见性;
    • 如果对象属性不是 volatile 类型的,newUpdater() 方法会抛出 IllegalArgumentException 这个运行时异常。
  • 原子化的累加器
    • DoubleAccumulator、DoubleAdder、LongAccumulator 和 LongAdder,这四个类仅仅用来执行累加操作,相比原子化的基本数据类型,速度更快,但是不支持 compareAndSet() 方法。
    • 如果你仅仅需要累加操作,使⽤原子化的累加器性能会更好。

http://www.ppmy.cn/news/235614.html

相关文章

百度推广一年多少钱,百度信息流广告投放一个月多少钱

百度广告投放的费用要看自己推广的地域、设定的关键词的数量、关键词的排名及价格决定的,如果推广的范围小,访问的人也少花钱就少,如果推广全国、关键词竞争激烈,每次访问的费用又偏高的话一天的消费肯定会很高的。行业不同、消费…

研究生要花多少钱?

前言 上个月,我们给大家分析了C9和两电一邮的研究生待遇。同样,各个院校专业研究生的学费也不尽相同,甚至部分专业能够达到数十万。 别着急,今天给大家介绍一下C9和两电一邮学费情况,我们整理了22年硕士研究生学费内…

网站一个月的花费是多少钱?

摘要: 做网站一个月多少钱?做网站所需要的费用千差万别,主要是看你选择的建站方式和对网站功能等需求。找 做网站一个月多少钱?做网站所需要的费用千差万别,主要是看你选择的建站方式和对网站功能等需求。找专业网站建设公司定制网站花费都…

微信小程序登录的最佳实践

微信小程序登录的最佳实践 官方文档的介绍 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。 登录流程时序 说明 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。 调用 auth.co…

Lecture 9 Lexical Semantics

目录 Introduction: sentiment analysis 引言:情感分析Word Semantics 单词语义Word meanings 单词含义WordNetSynsets 同义词集Noun Relations in WordNetHypernymy Chain 上位链Word SimilarityWord Similarity with PathsBeyond Path LengthAbstract NodesConcep…

数据安全--16--数据采集阶段安全防护措施

本博客地址:https://security.blog.csdn.net/article/details/131033616 一、引子 数据安全采集阶段的防护措施主要是从三个方面来开展的,第一个是从个人数据主体采集方面,第二个是从外部机构采集方面,以上两个方面基本涵盖了数…

win11锁屏方法

方法一、 首先,点击电脑主屏幕左下端的win图标,在弹出的界面点击admin图标。 然后,在弹出的选框中,点击【锁定】即可锁屏。 方法二、 锁屏快捷键和手动锁屏方式是:同时按住键盘win键L键。

在ubuntu20.04中设置锁屏背景(亲测有效)

在ubuntu20.04中设置锁屏背景 1.新建文件夹 打开终端输入: cd ~ mkdir software cd software/ mkdir images在根目录创建一个software文件夹,然后在software文件夹下创建一个images文件夹,用于存放背景图片。 2. 下载change-gdm-backgro…