自定义Lock以及ReadWriterLock

自定义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();
       }
    }

}
posted @ 2019-03-24 16:04  刘丽刚  阅读(306)  评论(0编辑  收藏  举报