自定义Lock以及ReadWriterLock
基于synchronize实现自定义版Lock
//自定义MyLock接口
public interface MyLock {
class TimeOutException extends Exception {
public TimeOutException(String message) {
super(message);
}
}
void lock() throws InterruptedException;
void lock(long mills) throws InterruptedException, TimeOutException;
void unlock();
Collection<Thread> getBlockedThread();
int getBlockedSize();
}
public class MyBooleanLock implements MyLock {
private boolean initVlaue = false;
private Collection<Thread> blockedThreadCollection = new ArrayList<>();
private Thread currrentThread;
public MyBooleanLock() {
initVlaue = false;
}
@Override
public synchronized void lock() throws InterruptedException {
while (initVlaue) {
blockedThreadCollection.add(Thread.currentThread());
this.wait();
}
blockedThreadCollection.remove(Thread.currentThread());
this.initVlaue = true;
this.currrentThread = Thread.currentThread();
}
@Override
public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
if (mills <= 0){
lock();
}
long hasRemaining = mills;
long endTime = System.currentTimeMillis() + mills;
while (initVlaue) {
if (hasRemaining <= 0 ){
throw new TimeOutException("Time Out");
}
blockedThreadCollection.add(Thread.currentThread());
this.wait(mills);
hasRemaining = endTime - System.currentTimeMillis();
}
blockedThreadCollection.remove(Thread.currentThread());
this.initVlaue = true;
this.currrentThread = Thread.currentThread();
}
@Override
public synchronized void unlock() {
//这里一定的判断,也就是确保lock线程只能被自己给unlock
if (Thread.currentThread() == currrentThread) {
this.initVlaue = false;
System.out.println(Thread.currentThread() + " release the lock monitor.");
this.notifyAll();
}
}
@Override
public Collection<Thread> getBlockedThread() {
return Collections.unmodifiableCollection(blockedThreadCollection);
}
@Override
public int getBlockedSize() {
return blockedThreadCollection.size();
}
}
public class LockTest {
final static MyBooleanLock lock = new MyBooleanLock();
public static void main(String[] args) {
LockTest test = new LockTest();
new Thread(() -> test.m1(),"t1").start();
new Thread(() -> test.m1(),"t2").start();
}
private void m1() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " start ");
TimeUnit.SECONDS.sleep(10);
}catch (InterruptedException e){
}finally {
lock.unlock();
}
}
}
基于synchronized实现自定义版ReadWriterLock
public class ReadWriterLock {
private int readingReaders = 0;
private int waitingReaders = 0;
private int writeringWriters = 0;
private int waitingWriters = 0;
// private Thread currentThread = null;
/**
threadLocal主要是用于对于取到了锁的线程做出一个标记,这样的话,在释放锁的时候,
如果该线程已经有了一个标记,说明其是上过锁的,可以对其进行释放锁,否则我们无法
对释放锁做出一个正确判断,总不能该线程并没有获取到锁也对其进行释放锁操作吧?
如果采用上面注释的currentThread来标记获取锁的线程,是有问题的,因为读锁与读锁之间
是可以同时获取锁的,加入有两个读锁同时获取到的锁,所以这个currentThread会被后面的
这个读锁修改currentThead变量,这样的话在判断会导致第一个读锁永远无法释放锁,而产生死锁的情况
*/
private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public synchronized void readLock() {
try {
this.waitingReaders++;
while (writeringWriters > 0 ){
this.wait();
}
threadLocal.set(1);
this.readingReaders++;
}catch (InterruptedException e){
}finally {
this.waitingReaders--;
}
}
public synchronized void readUnLock() {
/**
* 不能使用判断语句,因为在这里读与读是并发的,所以会覆盖掉currentThread这个局部变量
*/
/*if (currentThread == Thread.currentThread()) {
System.out.println(Thread.currentThread().getName() + "==================");
this.readingReaders--;
this.notifyAll();
}*/
/**
为什么这里需要做一个判断呢?
总不能让其在任何地方都能释放该锁吧?所以我们只能让对应的上了锁的线程才能释放锁
*/
if (threadLocal.get() != null && threadLocal.get() == 1){
System.out.println(Thread.currentThread().getName() + " release the lock ");
this.readingReaders--;
this.notifyAll();
}
}
public synchronized void writerLock() {
try {
this.waitingWriters++;
while (readingReaders >0 || writeringWriters >0 ){
this.wait();
}
threadLocal.set(1);
this.writeringWriters++;
}catch (InterruptedException e) {
}finally {
this.waitingWriters--;
}
}
public synchronized void writerUnLock() {
/* if (currentThread == Thread.currentThread()) {
this.writeringWriters--;
this.notifyAll();
}*/
if (threadLocal.get() != null && threadLocal.get() == 1) {
System.out.println(Thread.currentThread().getName() + " release the lock ");
this.writeringWriters--;
this.notifyAll();
}
}
}