惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News - Newest:
Hacker News - Newest: "LLM"
S
SegmentFault 最新的问题
The Cloudflare Blog
T
The Exploit Database - CXSecurity.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
有赞技术团队
有赞技术团队
www.infosecurity-magazine.com
www.infosecurity-magazine.com
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
The Hacker News
The Hacker News
人人都是产品经理
人人都是产品经理
阮一峰的网络日志
阮一峰的网络日志
大猫的无限游戏
大猫的无限游戏
L
Lohrmann on Cybersecurity
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
T
Threat Research - Cisco Blogs
博客园 - 叶小钗
量子位
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
S
Secure Thoughts
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
Help Net Security
Help Net Security
爱范儿
爱范儿
C
Cybersecurity and Infrastructure Security Agency CISA
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
Check Point Blog
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
T
Tor Project blog
NISL@THU
NISL@THU
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
The Register - Security
The Register - Security
Recent Announcements
Recent Announcements
N
News and Events Feed by Topic
B
Blog RSS Feed

青空之蓝

[青空之蓝-2023] - 色彩 | 青空之蓝 [青空之蓝-2022] - 平静 | 青空之蓝 [青空之蓝-2021] - 远望 | 青空之蓝 浅谈垃圾回收 | 青空之蓝 浅谈泛型擦除 | 青空之蓝 浅谈单点登录 | 青空之蓝 使用 Kotlin 编写 Spring 测试 | 青空之蓝 设计模式系列文章 | 青空之蓝 从零实现一个 Java 微框架 - IoC | 青空之蓝 从零实现一个 Java 微框架 - 前言 | 青空之蓝 浅谈 JVM:类加载 | 青空之蓝 浅谈 IO | 青空之蓝 浅谈并发:synchronized & ReentrantLock | 青空之蓝 浅谈并发:ThreadLocal | 青空之蓝 浅谈并发:三大特性 | 青空之蓝 浅谈组合注解 & 注解别名 | 青空之蓝 [青空之蓝-2020]-迷茫 | 青空之蓝 Java 系列文章 | 青空之蓝 HTTP 系列文章 | 青空之蓝 浅谈 EatWhatYouKill | 青空之蓝 浅谈可扩展线程池 | 青空之蓝 聊聊写框架 | 青空之蓝 聊聊现状-[2020-09] | 青空之蓝 浅谈并发:锁 | 青空之蓝 浅谈并发:基础 | 青空之蓝 浅谈缓存 | 青空之蓝 无须定义类,Spring 快速注入 Json 参数 | 青空之蓝 浅谈 Proxy 和 Aop | 青空之蓝 从零实现一个 PHP 微框架 - 初始化请求 | 青空之蓝 为 Vue3 添加一个简单的 Store | 青空之蓝 从零实现一个 PHP 微框架 - 服务提供者 | 青空之蓝 WSL2 踩坑记录 | 青空之蓝 浅谈浏览器Event Loop [更新] | 青空之蓝 从零实现一个 PHP 微框架 - Bootstrap 启动加载 | 青空之蓝 从零实现一个 PHP 微框架 - IoC 容器 | 青空之蓝 从零实现一个 PHP 微框架 - PSR & Composer | 青空之蓝 从零实现一个 PHP 微框架 - 前言 | 青空之蓝 MVVM 简单实现 | 青空之蓝 浅谈 DI 和 IoC | 青空之蓝 中间件实现 [PHP] | 青空之蓝 告别 Windows 终端的难看难用,打造好用的 PowerShell | 青空之蓝 VSCode Java输出中文乱码问题解决[更新] | 青空之蓝 浅谈浏览器渲染 | 青空之蓝 Vue-Cli@2 项目迁移日志 | 青空之蓝 Laragon & Scoop 集成踩坑记录 | 青空之蓝 「一行代码」优雅管理 Windows 软件 | 青空之蓝 [青空之蓝-2019]-年度总结 | 青空之蓝 为Vue添加简单的Store | 青空之蓝 为React添加简单的Store | 青空之蓝 为Vuex添加同步Action | 青空之蓝 浅谈B+树 | 青空之蓝 浅谈跳表 | 青空之蓝 浅谈数据库索引 | 青空之蓝 MySQL事务隔离 | 青空之蓝 算法复杂度分析(1) | 青空之蓝 一年来的经验总结 | 青空之蓝 Acrylic - VSCode Extension | 青空之蓝 ace编辑器设置惯性滚动 | 青空之蓝 Java二叉树实现 | 青空之蓝 Java图实现 | 青空之蓝 为apt方式安装的nginx重新编译增加WebDAV | 青空之蓝 XK-Editor - 一个支持富文本和Markdown的编辑器 | 青空之蓝 JS生成列表树 | 青空之蓝 Laravel生成目录树 | 青空之蓝 XK-Note - 集各种神奇功能的云笔记 | 青空之蓝 PHP GD生成验证码 | 青空之蓝 PHP GD图片处理[转换格式-水印-缩略图] | 青空之蓝 Origami - 简洁轻快的WordPress主题 | 青空之蓝 为WordPress启用WorkBox | 青空之蓝 [青空之蓝-2018]-年度总结 | 青空之蓝 VSCode Java手动导入jar和源码包 | 青空之蓝 Windows IP变化自动发送邮件 | 青空之蓝 C链表实现重制版 | 青空之蓝 C 结构体的定义和使用 | 青空之蓝 图的搜索(遍历) - BFS & DFS | 青空之蓝 Java链表实现 | 青空之蓝 C 快速排序 | 青空之蓝 C 插入排序 | 青空之蓝 C 归并排序 | 青空之蓝 C语言链表实现 | 青空之蓝 VSCode配置Java调试环境[Windows] | 青空之蓝 C 选择排序 | 青空之蓝 C 冒泡排序 | 青空之蓝 VSCode配置PHP调试环境[Windows] | 青空之蓝 VSCode配置C/C++ GDB调试环境[Windows] | 青空之蓝 WordPress友情链接模板 | 青空之蓝 Intel Optane 傲腾内存体验 | 青空之蓝 Mysql双机热备实战 | 青空之蓝 博客一年记录 | 青空之蓝 为WordPress启用Service Worker | 青空之蓝 Bing每日一图API | 青空之蓝 iframe延迟加载 | 青空之蓝 写在2018年高考前 | 青空之蓝 The Fox主题汉化分享 | 青空之蓝 [青空之蓝-2017]-崭新 | 青空之蓝 本博客评论规则 | 青空之蓝 世界,您好! | 青空之蓝
浅谈并发:CAS & AQS | 青空之蓝
Otstar Lin · 2021-02-13 · via 青空之蓝

前言

这篇文章躺在草稿里 6 个月了,最近才发现 2333,于是翻出来补全了下。

CAS

**CAS(Compare-and-Swap 比较和替换)**故名思意就是先比较然后替换的操作方式,是原子操作中的一种,同时也是无锁操作中的一种。在 Java 中广泛使用,常见的如 AQS 的更新状态、CopyOnWriteArrayList

通常情况下,我们操作某个共享资源,为了防止其他进程的干扰,我们通常会给这个共享资源加上一把锁,然而加锁,释放锁,竞争锁,线程的阻塞和唤醒是非常耗能的操作。而 CAS 采用的是记录内存位置和原始值,当记录的原始值与当前内存位置的值(当前值)相同的时候,就将新值更新到内存。如果不同说明在这过程中有其他线程干扰,执行失败策略。由于是无锁的操作,所以便没有了加锁和释放锁间一系列的额外开销,所以非常快。

流程

在进行 CAS 操作前需要三个操作参数:

  • 内存位置 V(它的值是我们想要去更新的)
  • 预期原值 A(上一次从内存中读取的值)
  • 新值 B(应该写入的新值)

操作过程:

先从 V 中取值,与 A 比较,如果相等则将 V 中的值更新成 B,如果不相等,说明 V 上的值被修改过了,也就是其他线程干扰了,这时候就不更新,进入失败的操作流程,比如重试,报错等。

缺点

当然如果 CAS 真的这么好用的话 Java 中早就放弃锁了。CAS 虽然很高效的解决原子操作,但是 CAS 仍然存在三大问题,同时也有使用场景的限制。

ABA 问题

原因:由于 CAS 是通过比较来判断是否进行更新操作,如果一个值从 A 变成 B,然后又被改成 A,在 CAS 检查时会认为值是没变的,实际上是变化了。

解决方法:为每次操作都加上版本号,如果版本号有变,即使值没变也说明是有变化的。

循环时间长开销大

原因:如果自旋长时间不成功,则会给 CPU 带来很大的执行开销。

解决方法:利用 pause 指令提升自旋性能。

只能保证一个值的原子操作

原因:如果有多个值需要同时操作,那么用 CAS 就无法简单解决了。

解决方案:可以对值进行合并,比如封装成一个对象等等。

使用场景限制

从 CAS 流程中我们可以看到,为了记录原始值,我们需要复制一份值,而这复制过程消耗的性能在少量的情况下并不明显,相比于锁更优。然而如果大量的执行 CAS 操作,或者操作的内容是比较庞大的,那么这些性能损耗就不能忽视了,较为极端的情况下甚至比锁还要差上很多。

AQS

AQS(AbstractQueuedSynchronizer 抽象排队同步器),是一个用来构建锁和同步器的框架,使用 AQS 能方便的构建出不同使用场景的同步器,常见的如 ReentrantLockCountDownLatch。AQS 采用模板方法模式,实现大量通用方法,子类通过继承方式实现其抽象方法来管理同步状态。

流程

当某个线程从 AQS 获取共享资源的时候,如果被请求的共享资源空闲,那么就将该线程设置为工作线程,然后锁定共享资源。如果被请求的共享资源被占用,那么就将线程加入 CLH 队列中,同时阻塞线程,进行排队等待。

CLH 队列

CLH 队列是一个虚拟的 FIFO 的双向队列。头节点是一个获取同步状态成功的节点。线程通过 AQS 获取锁失败,就会将线程封装成一个 Node 节点,插入队列尾。当有线程释放锁时,后唤醒头节点的 next 节点(第二个节点)尝试占用锁。

同步状态

在 AQS 中有一个 state 字段用于表示同步状态,使用了 volatile 关键字修饰,实现类可以通过 CAS 方式来更新同步状态。

资源共享模式

AQS 有两种资源共享模式:

  • 独占(Exclusive):即同一时间内只有一个线程能够获取共享资源。常见的实现如 ReentrantLock
  • 共享(Share):即一个共享资源可被多个线程同时使用。常见的实现如 CountDownLatch

AQS 为这两种资源共享模式提供了两组不同的方法,如独占式的 acquirerelease,共享式的 acquireSharedreleaseShared。按场景重写不同模式的方法即可实现不同的资源共享模式。当然也可以同时使用,比如 ReentrantReadWriteLock 就实现了独占和共享两种模式。

阻塞与唤醒

当有线程获取到共享资源了,其他线程获取时需要阻塞,当线程释放共享资源后,AQS 会负责唤醒在排队的线程。

AQS 通过 LockSupport 是用来创建锁和其他同步类的线程阻塞工具类,可以让线程在任意位置阻塞。每个使用 LockSupport 的线程都会与一个许可关联,如果该许可可用,则调用 park() 方法将会立即返回(加锁),否则会阻塞。如果许可尚不可用,则可以调用 unpark 使其可用(释放锁)。类似于 Object 类的 waitnotify

结语

ReentrantLock 相关的东西就暂时不再这篇文章写了,打算放到下一篇。

浅谈并发:CAS & AQS

https://blog.ixk.me/post/talking-about-concurrent-cas-and-aqs
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2021/02/13

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

浅谈并发:synchronized & ReentrantLock浅谈并发:ThreadLocal