锁升级:偏向锁、轻量级锁、重量级锁的过渡。
https://blog.csdn.net/haoranhaoshi/article/details/92388612
优先尝试低级锁,不能适用,就升级锁。线程获取到不被其他线程获取的监视类或对象,监视类或对象头部记录线程ID,线程退出对监视类或对象的获取时直接退出,是偏向锁。如果有其他线程来获取监视类或对象,发现头部记录的线程ID不是自己的ID(https://blog.csdn.net/haoranhaoshi/article/details/108501633),就升级为轻量级锁。轻量级锁采用CAS机制(https://blog.csdn.net/haoranhaoshi/article/details/108507092),尝试一定次数(默认10)获取不到监视类或对象,则升级为重量级锁(一旦获取不到监视类或对象就阻塞(https://blog.csdn.net/haoranhaoshi/article/details/108461058))。
因为操作唤醒阻塞的线程需从用户态切换到内存态,开销大,所以才优先使用轻量级锁进行循环判断是否可获取监视类或对象。
锁降级:写锁降级成为读锁。持有写锁的同时,获取到读锁,然后释放写锁。避免读到被其他线程修改的数据。
oracle官网锁降级示例:
class CachedData {
Object data;
volatile boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
// 缓存无效
if (!cacheValid) {
// Must release read lock before acquiring write lock
// 释放读锁
rwl.readLock().unlock();
// 尝试获取写锁
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
// 再次判断获取是否无效
if (!cacheValid) {
// 获取数据
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
// 锁降级
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}
// 经过很长的时间做一些处理、而且不想我刚刚自己更新的数据被别人改了
try {
use(data);
} finally {
rwl.readLock().unlock();
}
}
}