您的位置:首页 > 编程语言 > Java开发

Java并发编程:重入锁(ReentranceLock )、读写锁(ReadWriteLock)代码实现

2018-01-13 17:03 615 查看
重入锁:

同一时刻只能有一条线程拥有重入锁,但此线程可以重复获得锁。
其余需求获得此锁的线程被阻塞。
代码实现关键是记录当前获得锁的线程。
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  重入锁 读写锁