• 自定义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();
           }
        }
    
    }
    
  • 相关阅读:
    vscode常用插件列表
    使用docker构建supervisor全步骤
    docker删除虚悬镜像(临时镜像文件)
    消息队列的对比
    ECharts使用:this.dom.getContext is not a function
    curl命令行请求
    工作工具清单
    《SQL优化入门》讲座总结
    初始化git库并配置自动部署
    php代码进行跨域请求处理
  • 原文地址:https://www.cnblogs.com/liuligang/p/10588581.html
Copyright © 2020-2023  润新知