关于Java多线程-可见性、CAS、AQS、锁
前提
解决多线程操作出现的脏读和数据、操作不一致问题。
volatile可见性
Java 内存分为主内存和工作内存。
正常情况每个线程都拥有自己的工作内存,然后每隔一段时间会同步到主内存上,因此会存在不一致的情况。而volatile
则是为了让标记字段的读取和写入都是在主内存中,保证其一致性。注意:
但其仍不能保证写入操作的原子性。
CAS
Compare And Swap
, 比较并交换。用于解决多线程使用锁造成的性能损耗。
Java 是利用Unsafe
来实现CAS,进行硬件级别的原子性操作。
AQS
AbstractQueuedSynchronizer
, 这个为 Java 类, 公平锁FairSync
和非公平锁NonfairSync
均是通过此实现的。
其利用队列来实现阻塞锁和同步。
ABA 问题
情景: 初始值为A[线程1获取的值为A][线程2获取的值为A,并更改值A为值B,再更改值B为值A][线程1更改值A为值B]。
出现问题: 线程1感觉不到值有一段变化的过程,这是乐观锁
出现的问题。
解决方案:AtomicStampedReference
/AtomicMarkableReference
你值得拥有。
- AtomicStampedReference 每次修改会存储版本号,版本号实现用int。
- AtomicMarkableReference 每次修改会存储版本号,版本号实现用boolean。
锁的名词
可重入锁
- 已获取的锁可以不必去重新申请。
- synchronized/ReentrantLock 是可重入锁.
可中断锁
- 可以取消申请锁的操作。
- synchronized 不是可中断锁。
公平锁
- 公平锁是根据请求顺序分发锁, 唤醒需要时间,能保- 证操作的顺序。
- 非公平锁会出现插队情况,性能高,但是不能保证操作的顺序。
- synchronized 不是公平锁。
ReentrantLock
/ReentrantReadWriteLock
默认情况是非公平锁NonfairSync
,但可以设置为公平锁FairSync
乐观锁
每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功为止。
Atomic* 乐观锁
由于在多线程操作中无法保证操作的原子性,因此引入了锁和CAS。
AtomicStampedReference
/AtomicMarkableReference
用于解决 CAS 的 ABA 问题
单
- AtomicInteger
Integer类型
- AtomicLong
Long类型
- AtomicBoolean
Boolean类型
,内部使用int实现。 - AtomicReference
对象类型
数组
- AtomicIntegerArray
Integer数组
- AtomicLongArray
Long数组
- AtomicReferenceArray
对象数组
对象内字段
- AtomicIntegerFieldUpdater
对象内Integer类型字段
- AtomicLongFieldUpdater
对象内Long类型字段
- AtomicReferenceFieldUpdater
对象内对象类型字段
根据版本号进行操作
- AtomicStampedReference 每次修改会存储版本号,版本号实现用int。
- AtomicMarkableReference 每次修改会存储版本号,版本号实现用boolean。
锁和同步
锁和同步的作用
保证代码区域在同一时间只运行一个线程去执行,其余线程处于阻塞状态(BLOCKED)
。锁和同步的差异。
- 作用范围, Lock 可以跨方法,synchronized 只能在同一个方法中。
- 公平锁, Lock 使用公平锁,synchronized 使用非公平锁。
- 可中断,Lock 可以使用
lockInterruptibly()
中断锁,synchronized 无法中断。 - 当 synchronized 无法访问时会被阻塞,Lock 提供
tryLock()
减少阻塞时间。
- 不释放锁操作
- 同步代码中使用
Thread.sleep
/Thread.yield
, 线程处于WAITING
/TIMED_WAITING
状态 - 同步代码中线程被
suspend()
- 会释放锁操作
- 同步代码被break、return
- 同步代码被异常或错误终止
- 同步代码块执行结束
- 同步代码块被 wait(), 线程处于
WAITING
/TIMED_WAITING
状态
锁Lock
的相关实现
NonfairSync
、FairSync
ReentrantLock
1 |
|
ReentrantReadWriteLock
读写锁
1 | /** |
StampedLock
邮票锁, ReentrantReadWriteLock 的升级版
写锁、读锁、新增(乐观读锁、锁的转换)
1 |
|
Synchronized
使用级别
- 实例对象函数
this锁
- 静态函数
class锁
- 代码块
指定的锁
1 | public class SynchronizedTest { |