重入锁:
- 同一时刻只能有一条线程拥有重入锁,但此线程可以重复获得锁。
- 其余需求获得此锁的线程被阻塞。
- 代码实现关键是记录当前获得锁的线程。
public class ReentranceLock { //记录当前获得锁的线程。 private Thread lockedBy = null; private boolean isLocked = false; private int lockCount = 0; public synchronized void lock() throws InterruptedException { Thread callingThread = Thread.currentThread(); while (isLocked && lockedBy != callingThread) { wait(); } isLocked = true; lockedBy = callingThread; lockCount++; } public synchronized void unlock() { if (Thread.currentThread() == lockedBy) { lockCount--; if (lockCount == 0) { isLocked = false; notify(); } } } }
读/写锁:
1.线程获得读锁条件
- 没有其他线程已获得写锁,并且没有其他线程需求写锁(Read Access)
- 此线程已获得读锁(Read Reentrance)
- 此线程已获得写锁(Write to Read Reentrance)
2.线程获得写锁条件
- 没有其他线程已获得写锁,或者写锁(Write Access)
- 此线程已获得写锁(Write Reentrance)
- 此线程已获得读锁,且为唯一一个线程获得读锁(Read to Write Reentrance)
public class ReadWriteLock { //多个线程课同时获得读锁,用map记录线程以及对应线程获取锁次数 private Map<Thread, Integer> readingThreads = new HashMap<>(); //同一时刻,仅有一个线程可以获得写锁 private Thread writingThread = null; //获得写锁的线程获得锁的次数 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(); //当前线程没有获得读锁,抛出异常 if (!isReader(callingThread)) { throw new IllegalMonitorStateException( "Calling Thread does not" + " hold a read lock on this ReadWriteLock"); } int accessCount = getAccessCount(callingThread); if (accessCount == 1) { readingThreads.remove(callingThread); } else { readingThreads.put(callingThread, (accessCount - 1)); } notifyAll(); } //此线程是否可以获得读锁 private boolean canGrantReadAccess(Thread callingThread){ if(isWriter(callingThread)) return true; if(writers > 0) return false; if(isReader(callingThread)) return true; if(writeRequests > 0) return false; return true; } //此线程是否已经获得读锁 private boolean isReader(Thread callingThread){ return readingThreads.get(callingThread) != null; } //此线程是否已经获得读锁的次数 private int getAccessCount(Thread callingThread){ Integer accessCount = readingThreads.get(callingThread); if( accessCount == null) return 0; return accessCount.intValue(); } public synchronized void lockWrite() throws InterruptedException { writeRequests++; Thread callingThread = Thread.currentThread(); while(! canGrantWriteAccess(callingThread)){ wait(); } writeRequests--; writers++; 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"); } writers--; if (writers == 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 callingThread){ return readingThreads.size() == 1 && readingThreads.get(callingThread) != null; } }参考: Java Concurrency / Multithreading Tutorial