锁降级

简介: 锁降级

锁降级

锁降级指的是写锁降级成为读锁。如果当前线程拥有写锁,然后将其释放,最后再获取读锁,这种分段完成的过程不能称之为锁降级。锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程。

锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程。

示例:


public void processData() {
        readLock.lock();
        if (!update) {
            // 必须先释放读锁
            readLock.unlock();
            // 锁降级从写锁获取到开始
            writeLock.lock();
            try {
                if (!update) {
                    // 准备数据的流程(略)
                    update = true;
                }
                readLock.lock();
            } finally {
                writeLock.unlock();
            }
            // 锁降级完成,写锁降级为读锁
        }
        try {
            // 使用数据的流程(略)
        } finally {
            readLock.unlock();
        }
    }

只有一个线程能够获取到写锁,其他线程会被阻塞在读锁和写锁的lock()方法上。当前线程获取写锁完成数据准备之后,再获取读锁,随后释放写锁,完成锁降级。

因为数据不常变化,所以多个线程可以并发地进行数据处理,当数据变更后,如果当前线程感知到数据变化,则进行数据的准备工作,同时其他处理线程被阻塞,直到当前线程完成数据的准备工作。

为了保证数据的可见性,如果当前线程不获取读锁而是直接释放写锁,假设此刻另一个线程(记作线程T)获取了写锁并修改了数据,那么当前线程无法感知线程T的数据更新。如果当前线程获取读锁,即遵循锁降级的步骤,则线程T将会被阻塞,直到当前线程使用数据并释放读锁之后,线程T才能获取写锁进行数据更新。

RentrantReadWriteLock不支持锁升级(把持读锁、获取写锁,最后释放读锁的过程)。目的也是保证数据可见性,如果读锁已被多个线程获取,其中任意线程成功获取了写锁并更新了数据,则其更新对其他获取到读锁的线程是不可见的。

当前线程 其他线程 是否阻塞
读锁 读锁 不阻塞
读锁 写锁 阻塞
写锁 读锁 阻塞
写锁 写锁 阻塞
相关文章
|
28天前
|
C++
多线程(锁策略, synchronized 对应的锁策略)
多线程(锁策略, synchronized 对应的锁策略)
26 2
|
28天前
|
Java 编译器
多线程(锁升级, 锁消除, 锁粗化)
多线程(锁升级, 锁消除, 锁粗化)
26 1
|
1月前
多线程并发锁的方案—互斥锁
多线程并发锁的方案—互斥锁
|
1月前
多线程并发锁方案—自旋锁
多线程并发锁方案—自旋锁
|
安全 Java 调度
认识并发中常见的锁
1. 锁的作用 2. 乐观锁和悲观锁 1)乐观锁 2)悲观锁 3)乐观锁和悲观锁在 Java 中的典型实现 4)数据版本机制 3. CAS 机制 1)什么是 CAS 2)CAS 的 ABA 问题 4. 读写锁 1)Java 标准库中提供的读写锁 5. 偏向锁、轻量级锁和重量级锁 1)偏向锁 2)轻量级锁 3)重量级锁 6. 自旋锁 7. 公平锁和非公平锁
96 0
|
存储 Oracle 前端开发
synchronized 底层如何实现?什么是锁升级、降级?
synchronized 底层如何实现?什么是锁升级、降级?
467 0
synchronized 底层如何实现?什么是锁升级、降级?
轮询锁使用时遇到的问题与解决方案!(1)
轮询锁使用时遇到的问题与解决方案!(1)
71 0
轮询锁使用时遇到的问题与解决方案!(1)
轮询锁使用时遇到的问题与解决方案!(4)
轮询锁使用时遇到的问题与解决方案!(4)
96 0
轮询锁使用时遇到的问题与解决方案!(4)
轮询锁使用时遇到的问题与解决方案!(6)
轮询锁使用时遇到的问题与解决方案!(6)
76 0
轮询锁使用时遇到的问题与解决方案!(6)
轮询锁使用时遇到的问题与解决方案!(3)
轮询锁使用时遇到的问题与解决方案!(3)
82 0
轮询锁使用时遇到的问题与解决方案!(3)