Read / Write Locks in Java

原文: http://tutorials.jenkov.com/java-concurrency/read-write-locks.html
参考译文:https://blog.csdn.net/u011638883/article/details/18605761
读写锁,解决多读少写的同步问题。

实现

读获取,无线程写,也没有线程请求写操作。
写获取,没有线程读或者写。

一个线程想要进行读操作,必须满足此时没有写操作,已经没有写请求。在这里我们假定写请求比读请求更为重要,因为如果读操作非常多,写操作就很难获取到锁,很容易就进入到一个饥饿状态。线程写请求需要阻塞直到读锁全部释放。

示例

public class ReadWriteLock{
    private int readers       = 0;
    private int writers       = 0;
    private int writeRequests = 0;
    public synchronized void lockRead() throws InterruptedException{
        while(writers > 0 || writeRequests > 0){
            wait();
        }
        readers++;
    }
    public synchronized void unlockRead(){
        readers--;
        notifyAll();
    }
    public synchronized void lockWrite() throws InterruptedException{
        writeRequests++;
        while(readers > 0 || writers > 0){
            wait();
        }
        writeRequests--;
        writers++;
    }
    public synchronized void unlockWrite() throws InterruptedException{
        writers--;
        notifyAll();
    }
}

Read / Write Lock Reentrance

Read Reentrance

public class ReadWriteLock{
    private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
    private int writers = 0;
    private int writeRequests = 0;
    public synchronized void lockRead() throws InterruptedException{
        Thread callingThread = Thread.currentThread();
        while(! canGrantReadAccess(callingThread)){
            wait();
        }
        readingThreads.put(callingThread,
                (getAccessCount(callingThread) + 1));
    }
    public synchronized void unlockRead(){
        Thread callingThread = Thread.currentThread();
        int accessCount = getAccessCount(callingThread);
        if(accessCount == 1){ readingThreads.remove(callingThread); }
        else { readingThreads.put(callingThread, (accessCount -1)); }
        notifyAll();
    }
    private boolean canGrantReadAccess(Thread callingThread){
        if(writers > 0)            return false;
        if(isReader(callingThread) return true;
        if(writeRequests > 0)      return false;
        return true;
    }
    private int getReadAccessCount(Thread callingThread){
        Integer accessCount = readingThreads.get(callingThread);
        if(accessCount == null) return 0;
        return accessCount.intValue();
    }
    private boolean isReader(Thread callingThread){
        return readingThreads.get(callingThread) != null;
    }

}

Write Reentrance


public class ReadWriteLock {
    private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
    private int writeAccesses = 0;
    private int writeRequests = 0;
    private Thread writingThread = null;
    public synchronized void lockWrite() throws InterruptedException {
        writeRequests++;
        Thread callingThread = Thread.currentThread();
        while (!canGrantWriteAccess(callingThread)) {
            wait();
        }
        writeRequests--;
        writeAccesses++;
        writingThread = callingThread;
    }
    public synchronized void unlockWrite() throws InterruptedException {
        writeAccesses--;
        if (writeAccesses == 0) {
            writingThread = null;
        }
        notifyAll();
    }
    private boolean canGrantWriteAccess(Thread callingThread) {
        if (hasReaders()) return false;
        if (writingThread == null) return true;
        if (!isWriter(callingThread)) return false;
        return true;
    }
    private boolean hasReaders() {
        return readingThreads.size() > 0;
    }
    private boolean isWriter(Thread callingThread) {
        return writingThread == callingThread;
    }
}

Read to Write Reentrance

public class ReadWriteLock {
    private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
    private int writeAccesses = 0;
    private int writeRequests = 0;
    private Thread writingThread = null;
    public synchronized void lockWrite() throws InterruptedException {
        writeRequests++;
        Thread callingThread = Thread.currentThread();
        while (!canGrantWriteAccess(callingThread)) {
            wait();
        }
        writeRequests--;
        writeAccesses++;
        writingThread = callingThread;
    }
    public synchronized void unlockWrite() throws InterruptedException {
        writeAccesses--;
        if (writeAccesses == 0) {
            writingThread = null;
        }
        notifyAll();
    }
    private boolean canGrantWriteAccess(Thread callingThread) {
        if (isOnlyReader(callingThread)) return true;
        if (hasReaders()) return false;
        if (writingThread == null) return true;
        if (!isWriter(callingThread)) return false;
        return true;
    }
    private boolean hasReaders() {
        return readingThreads.size() > 0;
    }
    private boolean isWriter(Thread callingThread) {
        return writingThread == callingThread;
    }
    private boolean isOnlyReader(Thread thread) {
        return readers == 1 && readingThreads.get(callingThread) != null;
    }
}

Write to Read Reentrance

public class ReadWriteLock{
    private boolean canGrantReadAccess(Thread callingThread){
        if(isWriter(callingThread)) return true;
        if(writingThread != null)   return false;
        if(isReader(callingThread)  return true;
        if(writeRequests > 0)       return false;
        return true;
    }
}

Fully Reentrant ReadWriteLock

public class ReadWriteLock {
    private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
    private int writeAccesses = 0;
    private int writeRequests = 0;
    private Thread writingThread = null;
    public synchronized void lockRead() throws InterruptedException {
        Thread callingThread = Thread.currentThread();
        while (!canGrantReadAccess(callingThread)) {
            wait();
        }

        readingThreads.put(callingThread,
                (getReadAccessCount(callingThread) + 1));
    }
    private boolean canGrantReadAccess(Thread callingThread) {
        if (isWriter(callingThread)) return true;
        if (hasWriter()) return false;
        if (isReader(callingThread)) return true;
        if (hasWriteRequests()) return false;
        return true;
    }
    public synchronized void unlockRead() {
        Thread callingThread = Thread.currentThread();
        if (!isReader(callingThread)) {
            throw new IllegalMonitorStateException("Calling Thread does not" +
                    " hold a read lock on this ReadWriteLock");
        }
        int accessCount = getReadAccessCount(callingThread);
        if (accessCount == 1) {
            readingThreads.remove(callingThread);
        } else {
            readingThreads.put(callingThread, (accessCount - 1));
        }
        notifyAll();
    }
    public synchronized void lockWrite() throws InterruptedException {
        writeRequests++;
        Thread callingThread = Thread.currentThread();
        while (!canGrantWriteAccess(callingThread)) {
            wait();
        }
        writeRequests--;
        writeAccesses++;
        writingThread = callingThread;
    }
    public synchronized void unlockWrite() throws InterruptedException {
        if (!isWriter(Thread.currentThread()) {
            throw new IllegalMonitorStateException("Calling Thread does not" +
                    " hold the write lock on this ReadWriteLock");
        }
        writeAccesses--;
        if (writeAccesses == 0) {
            writingThread = null;
        }
        notifyAll();
    }
    private boolean canGrantWriteAccess(Thread callingThread) {
        if (isOnlyReader(callingThread)) return true;
        if (hasReaders()) return false;
        if (writingThread == null) return true;
        if (!isWriter(callingThread)) return false;
        return true;
    }
    private int getReadAccessCount(Thread callingThread) {
        Integer accessCount = readingThreads.get(callingThread);
        if (accessCount == null) return 0;
        return accessCount.intValue();
    }
    private boolean hasReaders() {
        return readingThreads.size() > 0;
    }
    private boolean isReader(Thread callingThread) {
        return readingThreads.get(callingThread) != null;
    }
    private boolean isOnlyReader(Thread callingThread) {
        return readingThreads.size() == 1 &&
                readingThreads.get(callingThread) != null;
    }
    private boolean hasWriter() {
        return writingThread != null;
    }
    private boolean isWriter(Thread callingThread) {
        return writingThread == callingThread;
    }
    private boolean hasWriteRequests() {
        return this.writeRequests > 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值