1.手写读写锁
通常情况下,我们只会调用api,当真正写的时候就写不出来了。还是要加强代码编写。
读写锁:读读不互斥,读写互斥,写写互斥
public class ReadWriteLock {
/**
* 读的线程数量
*/
private int readCount;
/**
* 读线程存储
*/
private Map<Thread,Integer> readThread = new HashMap<>();
/**
* 只能有一个写线程
*/
private Thread writeThread = null;
/**
* 保证可重入
*/
private int writeCount = 0;
/**
* 读锁 保证线程安全使用synchronized
* 读的时候不允许写
*/
public synchronized void lockRead() throws InterruptedException {
//判断是否可以读
Thread curThread = Thread.currentThread();
//判断是否可以进行读锁
if(!tryRead(curThread)) {
wait();
}
//可以获取读锁
readCount++;
readThread.put(curThread,readThread.getOrDefault(curThread,0)+1);
}
/**
* 判断是否可以读
* @param curThread
* @return
*/
private boolean tryRead(Thread curThread) {
if(writeThread!=null) {
return false;
}
return true;
}
/**
* 读解锁
*/
public synchronized void unLockRead() {
if(readCount==0) {
throw new RuntimeException("没有读锁线程");
}
Thread curThread = Thread.currentThread();
if(readThread.containsKey(curThread)) {
int size = readThread.get(curThread);
size--;
if(size==0) {
readThread.remove(curThread);
readCount--;
}
notifyAll();
}else{
throw new RuntimeException("权限不足,没有读锁");
}
}
/**
* 写锁
* 写的时候判断是否有读先吃
*/
public synchronized void lockWrite() throws InterruptedException {
Thread curThread = Thread.currentThread();
if(curThread==writeThread) {
//次数加1
writeCount++;
}
//判断是否有读锁
if(!tryWrite(curThread)) {
wait();
}
//可以加锁
writeThread = curThread;
writeCount++;
}
/**
* 判断是否可以写
* @param curThread
* @return
*/
private boolean tryWrite(Thread curThread) {
//先判断是否有写锁
if(curThread!=writeThread) {
return false;
}
//判断是否有读锁
if(readThread.size()>0) {
return false;
}
return true;
}
/**
* 写锁释放
*/
public synchronized void unLockWrite() {
//写锁释放
if(writeThread==null) {
throw new RuntimeException("当前没有写锁");
}
Thread curThread = Thread.currentThread();
if(writeThread!=curThread) {
throw new RuntimeException("没有解锁权限");
}
writeCount--;
if(writeCount==0) {
writeThread=null;
}
notifyAll();
}
}