读写锁的应用

读写锁在 Java 中是 ReentrantReadWriteLock,应用形式是:

import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockDemo implements TestDemo {    ReentrantReadWriteLock lock = new ReentrantReadWriteLock();    ReentrantReadWriteLock.ReadLock readLock = lock.readLock();    ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();    private int x = 0;    private void count() {        writeLock.lock();        try {            x++;        } finally {            writeLock.unlock();// 保障当读的时候如果出现异常,会开释锁,synchronized为什么不必呢?因为synchronized外部曾经帮咱们做了~        }    }    private void print(int time) {        readLock.lock();        try {            for (int i = 0; i < time; i++) {                System.out.print(x + " ");            }            System.out.println();        } finally {            readLock.unlock();// 保障当读的时候如果出现异常,会开释锁,synchronized为什么不必呢?因为synchronized外部曾经帮咱们做了~        }    }    @Override    public void runTest() {    }}

ReentrantReadWriteLock和ReentrantLock的区别?

应用ReentrantReadWriteLock读写锁的形式,会调用readLock()和writeLock()两个办法,看下他们的源码:

public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }

复制代码能够看到用到了WriteLock和ReadLock两个动态外部类,他们对锁的实现如下:

public static class ReadLock implements Lock, java.io.Serializable {    public void lock() {        sync.acquireShared(1); //共享    }    public void unlock() {        sync.releaseShared(1); //共享    }}public static class WriteLock implements Lock, java.io.Serializable {    public void lock() {        sync.acquire(1); //独占    }    public void unlock() {        sync.release(1); //独占    }}abstract static class Sync extends AbstractQueuedSynchronizer {}

看到这里发现了ReentrantReadWriteLock和ReentrantLock的一个相同点和不同点,
雷同的是应用了同一个要害实现AbstractQueuedSynchronizer,不同的是ReentrantReadWriteLock应用了两个锁别离实现了AQS,
而且WriteLock和ReentrantLock一样,应用了独占锁。

而ReadLock和Semaphore一样,应用了共享锁。

再往下的内容预计看过后面几篇文章的都很相熟了,独占锁通过state变量的0和1两个状态来管制是否有线程占有锁,共享锁通过state变量0或者非0来管制多个线程拜访。

在下面的代码中,ReadLock和WriteLock应用了同一个AQS,那么在ReentrantReadWriteLock中又是怎么管制读锁和写锁关系的呢?

这当中还有一个问题,因为16位最大全1示意为65535,所以读锁和写锁最多能够获取65535个。

ReentrantReadWriteLock会产生写饥饿的状况吗?如果产生,有没有比拟好的解决办法?

ReentrantReadWriteLock也会产生写申请饥饿的状况,因为写申请一样会排队,
不论是偏心锁还是非偏心锁,在有读锁的状况下,都不能保障写锁肯定能获取到,这样只有读锁始终占用,就会产生写饥饿的状况。
那么JDK就没有提供什么好方法来解决这个问题吗?
当然是有的,那就是JDK8中新增的改良读写锁---StampedLock.

本文由猿必过 YBG 公布