JAVA锁的工具类 - 两种基本方式
锁接口和类
2020年12月11日
13:58
1. synchronized的不足
虽然synchronized效率已经上来了,但是对比lock还是有一些缺点,主要还是灵活性方面。
-
无法实现乐观读锁 sleep的时候不释放锁会导致所有线程阻塞
常见锁的分类
-
可重入锁和非可重入锁,锁两次,是否已经作处理 公平锁非公平锁 读写锁和排他锁,排他锁是独占的,只有一个线程,读写锁可以是乐观锁的实现
2. JDK中的锁实现
2.1 AQS
参考AQS,此外,JDK中还有AQLS,它将资源标记换为long,AOS是它们的父类。
ReentrantLock
重要的独占锁参考AQS。这个锁是理解AQS的基础,也是理解其他锁的基础——其实是因为锁的实现比较类似。
2.1.1 使用
ReentrantReadWriteLock,这是JDK实现的一个读写锁,它包含读锁和写锁,其使用也简单。
但是它的缺点是,写锁是独占锁,一旦写,则读写线程都得阻塞。
2.1.2 原理
它的原理和ReentrantLock的区别是,它维护两对锁。
读锁和写锁有什么区别呢?一看源码就能理解了。
2.2 StampedLock
这与AQS平行的另一个锁实现,解决了ReentrantReadWriteLock的缺陷,即在写的时候也可以支持并发的读,它属于乐观锁实现。
在读的时候如果发生了写,应该通过重试的方式来获取新的值,而不应该阻塞写操作。这种模式也就是典型的无锁编程思想,和CAS自旋的思想一样。
2.2.1 使用
以下逻辑是,乐观读取,但万一发现发生了写(状态改变),那就需要使用悲观锁。
2.2.2 原理
从使用中可以看到,类似于乐观锁的实现,它是通过控制一个状态值(version)来指示出以乐观锁的方式去读取后,在这期间是否发生了改变。
从源码来看,状态实现蛮繁杂的。简单概括:
-
对于悲观锁的加锁和释放,分别对应着状态的加减 而悲观锁写锁,不管加锁或者解锁,状态只会增加,这是为了防止ABA问题 状态值的修改都是通过CAS实现的
上一篇:
IDEA上Java项目控制台中文乱码