读写锁的判定和可重入性
发布日期:2021-06-29 03:45:04 浏览次数:2 分类:技术文章

本文共 4235 字,大约阅读时间需要 14 分钟。

看了一个很好的关于读写线程的设计,支持可重入,代码写的很好,优秀的代码总是需要慢慢的专研和学习的,嘿嘿

package com.zcswl.syn;import java.util.HashMap;import java.util.Map;/** * 读线程不能够阻塞读线程, * 当前的读线程能够阻塞其他线程的写线程,自身拥有写线程 * 当前的写线程能够阻塞其他线程的读线程,自身拥有读线程,并且可重复获取当前的写线程 * @author zhouchenggong * */public class ReadWriterLockFinal {
private Map
readingThreads =new HashMap
(); //读线程Map集合 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(); } /** * 将当前的读线程加入到读线程的Map集合中,设置当前线程在集合中的int值 */ 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"); } /** * 在读线程的Map中获取,如果为1,表示的是读写第一次 */ int accessCount = getReadAccessCount(callingThread); if(accessCount == 1){ readingThreads.remove(callingThread); } else { //Map中没有改线程,加入进去 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; } //如果写线程不是null,true; private boolean hasWriter(){ return writingThread != null; } //如果当前的线程是写线程,true; private boolean isWriter(Thread callingThread){ return writingThread == callingThread; } private boolean hasWriteRequests(){ return this.writeRequests > 0; }}

转载地址:https://blog.csdn.net/zcswl7961/article/details/68487441 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:关于Spring容器中定时器到时执行会出现两个线程同时执行的问题
下一篇:mysql日志设置命令

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月07日 21时01分09秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章