首页 > 代码库 > JDK读写锁ReadWriteLock的升级和降级问题

JDK读写锁ReadWriteLock的升级和降级问题

JDK提供了写锁接口ReadWriteLock和它的实现ReentrantReadWriteLock。要实现一个读写锁,需要考虑很多细节,其中之一就是锁升级和锁降级的问题。什么是升级和降级呢?ReadWriteLock的javadoc有一段话:

Can the write lock be downgraded to a read lock without allowing an intervening writer? Can a read lock be upgraded to a write lock,in preference to other waiting readers or writers?

锁降级:从写锁变成读锁;锁升级:从读锁变成写锁。读锁是可以被多线程共享的,写锁是单线程独占的。也就是说写锁的并发限制比读锁高,这可能就是升级/降级名称的来源。

如下代码会产生死锁,因为同一个线程中,在没有释放读锁的情况下,就去申请写锁,这属于锁升级,ReentrantReadWriteLock是不支持的。

 ReadWriteLock rtLock = new ReentrantReadWriteLock();
 rtLock.readLock().lock();
 System.out.println("get readLock.");
 rtLock.writeLock().lock();
 System.out.println("blocking");

ReentrantReadWriteLock支持锁降级,如下代码不会产生死锁。

ReadWriteLock rtLock = new ReentrantReadWriteLock();
rtLock.writeLock().lock();
System.out.println("writeLock");

rtLock.readLock().lock();
System.out.println("get read lock");

这段代码虽然不会导致死锁,但没有正确的释放锁。从写锁降级成读锁,并不会自动释放当前线程获取的写锁,仍然需要显示的释放,否则别的线程永远也获取不到写锁。锁的释放和获取可以看下:可重入锁的获取和释放需要注意的一点儿事

final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Thread wt = new Thread(new Runnable()
{

    @Override
    public void run()
    {
        readWriteLock.writeLock().lock();
        System.out.println("writeLock");

        readWriteLock.readLock().lock();
        System.out.println("readLock");
        readWriteLock.readLock().unlock();

        System.out.println("block");
    }
});

wt.start();

Thread.sleep(100);

System.out.println("main blocking.");
readWriteLock.readLock().lock();