深入理解Java并发编程之共享模型无锁

本文介绍了无锁编程中的CAS操作和volatile关键字在确保线程安全中的作用。通过AtomicInteger等原子类的示例,展示了无锁并发如何提高效率。同时,讨论了ABA问题及其解决方案,并提到了原子引用和原子数组在并发编程中的应用。
摘要由CSDN通过智能技术生成
  1. 共享模型之无锁

概述

本章内容包括以下部分

  • CAS与volatile

  • 原子整数

  • 原子引用

  • 原子累加器

  • Unsafe

  1. 线程安全解决方法

有如下需求,保证account.withdraw取款方法的线程安全

线程不安全的原因

  • 单核的指令交错

  • 多核的指令交错

解决思路-锁

解决思路-无锁

  1. CAS与volatile

AtomicInteger解决线程安全问题的原理

其中的关键是compareAndSet,它的简称就是CAS(也有Compare And Swap的说法),它必须是原子操作。

慢动作分析

输出结果

volatile

获取共享变量时,为了保证该变量的可见性,需要使用volatile 修饰

它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取

它的值,线程操作volatile 变量都是直接操作主存。即一个线程对volatile 变量的修改,对另一个线程可见

为什么无锁效率高

  • 无锁情况下,即使重试失败,线程始终在高速运行,没有停歇,而synchronized 会让线程在没有获得锁的时候,发生上下文切换,进入阻塞。打个比喻

  • 线程就好像高速跑道上的赛车,高速运行时,速度超快,一旦发生上下文切换,就好比赛车要减速、熄火,等被唤醒又得重新打火、启动、加速... 恢复到高速运行,代价比较大

  • 但无锁情况下,因为线程要保持运行,需要额外 CPU 的支持,CPU 在这里就好比高速跑道,没有额外的跑道,线程想高速运行也无从谈起,虽然不会进入阻塞,但由于没有分到时间片,仍然会进入可运行状态,还是会导致上下文切换。

CAS的特点

结合CAS 和 volatile 可以实现无锁并发,适用于线程数少、多核 CPU 的场景下。

  • CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏点再重试呗。

  • synchronized 是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。

CAS 体现的是无锁并发、无阻塞并发,请仔细体会这两句话的意思

  • 因为没有使用 synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一

  • 如果竞争激烈,可以想到重试必然频繁发生,反而效率会受影响

  1. 原子整数

J.U.C 并发包提供了:

  • AtomicBoolean

  • AtomicInteger

  • AtomicLong

以 AtomicInteger 为例

  1. 原子引用

为什么需要原子引用类型?

  • AtomicReference

  • AtomicMarkableReference

  • AtomicStampedReference

不安全实现

安全实现-使用锁

安全使用-使用CAS

ABA问题及解决

ABA问题

主线程仅能判断出共享变量的值与最初值A 是否相同,不能感知到这种从 A 改为 B 又改回 A 的情况,如果主线程希望:

只要有其它线程【动过了】共享变量,那么自己的 cas 就算失败,这时,仅比较值是不够的,需要再加一个版本号AtomicStampedReference

输出为

AtomicStampedReference 可以给原子引用加上版本号,追踪原子引用整个的变化过程,如:A -> B -> A -> C ,通过AtomicStampedReference,我们可以知道,引用变量中途被更改了几次。

但是有时候,并不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了AtomicMarkableReference

AtomicMarkableReference

  1. 原子数组

  • AtomicIntegerArray

  • AtomicLongArray

  • AtomicReferenceArray

  1. 字段更新器

  • AtomicReferenceFieldUpdater // 域 字段

  • AtomicIntegerFieldUpdater

  • AtomicLongFieldUpdater

利用字段更新器,可以针对对象的某个域(Field)进行原子操作,只能配合 volatile 修饰的字段使用,否则会出现异常

  1. 原子累加器

累加器性能比较

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值