前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >乐观锁(CAS)

乐观锁(CAS)

作者头像
shysh95
发布2021-05-11 15:17:05
6680
发布2021-05-11 15:17:05
举报
文章被收录于专栏:shysh95shysh95

Hi~朋友,点点关注不迷路

多线程在提高我们程序的并发度的同时,也引入线程的安全问题,即多个线程对共享变量的操作是非线程安全的,为了解决线程安全问题,我们引入了锁。锁大体分为两类:

  • 乐观锁
  • 悲观锁

摘要

  1. 什么是乐观锁
  2. 什么是CAS
  3. CAS有什么优势
  4. CAS有什么缺点
  5. 如何防止CAS的ABA问题
  6. Atomic类

1. 乐观锁

乐观锁的概念其实很简单,就是在操作一个共享变量时,我们认为多个线程之间没有冲突。

2. CAS

CAS是乐观锁的一种实现,CAS全称是比较和替换,CAS的操作主要由以下几个步骤组成:

  1. 先查询原始值
  2. 操作时比较原始值是否修改
  3. 如果修改,则操作失败,禁止更新操作,如果没有发生修改,则更新为新值

上述三个步骤是一个原子性操作,不可以被拆分执行。

3. CAS的优势

CAS是一种无锁操作,不需要加锁,避免了线程切换的开销。

4. CAS的缺点

CAS虽然在低并发量的情况下可以减少系统的开销,但是CAS也有一些问题:

  • CPU开销过大问题
  • ABA问题
  • 只能针对一个共享变量

上图是我们在使用CAS的一个基本操作流程。

4.1 CPU开销过大

在我们使用CAS时,如果并发量过大,我们的程序有可能会一直自旋,长时间占用CPU资源。

4.2 ABA问题

假设有个共享变量J,原始值为1。

  1. 线程A读取变量J,值为1
  2. 线程B读取变量J,值为1
  3. 线程A变量J+1,CAS成功从1修改为2
  4. 线程C读取变量J,值为2
  5. 线程C将变量J-1,CAS成功从2修改为1
  6. 线程A通过CAS比较和替换,依然可以改为自己想修改的值

上述过程,线程B和C已经将变量J的值已经改变了,但是线程A无法发现,依然可以修改共享变量,这就产生了ABA问题。

4.3 共享变量单一

CAS操作单个共享变量的时候可以保证原子的操作,无法操作多个变量。但是在JDK5之后,AtomicReference可以用来保证对象之间的原子性,我们可以把多个对象放入CAS中操作。

5. 如何防止CAS的ABA

三个字:加标志位(version)。

至于标志位可以是自增的数字,也可以是时间戳。通过标志位我们可以精确的知道每次修改。

6. Atomic类

在java.util.concurrent.atomic包下,有一些以Atomic为前缀的类,里面大量使用了CAS操作,如下:

  • AtomicInteger
  • AtomicLong
  • AtomicBoolean
  • AtomicReference

本期的Java 乐观锁(CAS)介绍到这,我是shysh95,我们下期再见!!!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员修炼笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档