zoukankan      html  css  js  c++  java
  • 使用AQS自己实现一把锁

    使用AQS自己实现一把锁

    其实是想一把锁需要两点:  1. 锁状态( 0当前有线程在使用 1当前无线程在使用)   2.持有锁的线程(当前线程) 

    总结:就是当前如果有线程通过竞争cas成功了,则将 【锁状态】设为1,将持有锁的线程记录起来。  这样就能防止其他线程再获取。

    我们知道要是实现一个自定义的 Lock 实现类,首先要实现 Lock 接口,并且定义一个内部类继承 AQS 类,重写他的方法

    package com.middle.aqsdemo;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.AbstractQueuedSynchronizer;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    
    /**
     * @author 15510
     * @create 2019-07-31 17:10
     */
    public class SimplifyReentrantLock implements Lock {
    
        private final Sync sync = new Sync();
    
        /**
         * AQS的子类Sync
         */
        private static class Sync extends AbstractQueuedSynchronizer {
    
            @Override
            protected boolean isHeldExclusively() {
                //是否处于占用状态
                return getState() == 1;
            }
    
            @Override
            protected boolean tryAcquire(int arg) {
                //当状态为0是获取锁
                if (compareAndSetState(0, 1)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
                return false;
            }
    
            @Override
            protected boolean tryRelease(int arg) {
                //释放锁,将状态设置为0
                if (getState() == 0) {
                    throw new IllegalMonitorStateException();
                }
                setExclusiveOwnerThread(null);
                setState(0);
                return true;
            }
    
            Condition newCondition() {
                return new ConditionObject();
            }
    
        }
    
        @Override
        public void lock() { sync.acquire(1); }
    
        @Override
        public void unlock() { sync.release(1); }
    
        @Override
        public Condition newCondition() { return sync.newCondition(); }
    
        @Override
        public boolean tryLock() { return sync.tryAcquire(1); }
    
        @Override
        public void lockInterruptibly() throws InterruptedException { }
    
        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }
    }
    
    package com.middle.aqsdemo;
    
    import java.util.concurrent.locks.Condition;
    
    /**
     * @author 15510
     * @create 2019-07-31 17:12
     */
    public class SimplifyReentrantLockDemo {
    
        public static void main(String[] args) {
            SimplifyReentrantLock lock = new SimplifyReentrantLock();
            Condition condition = lock.newCondition();
    
            new Thread(() -> {
                lock.lock();
                try {
                    System.out.println("进入等待!");
                    condition.await(); // 释放锁
                    System.out.println("接收到通知!继续执行!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.unlock();
            }, "conditionAwaitThread").start();
    
            new Thread(() -> {
                try {
                    System.out.println("模拟3秒后发送通知过!");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.lock();
                System.out.println("发送通知!");
                condition.signal();
                lock.unlock();
            }, "conditionSignalThread").start();
        }
    }
    

    执行结果

    进入等待!
    模拟3秒后发送通知过!
    发送通知!
    接收到通知!继续执行!
    
    Process finished with exit code 0
  • 相关阅读:
    如何把项目上传到github
    springBoot整合Mybatis为什么可以省略mybatis-config.xml
    【Mybatis源码解析】-mybatis-spring原理解析
    没有名字 [整除分块优化dp]
    替身使者 [区间dp]
    P3158 [CQOI2011]放棋子 [动态规划]
    博士之时 [分类讨论, 计数]
    曾有两次 [最短路树]
    序列 [线段树]
    城镇 [树的直径, 启发式合并]
  • 原文地址:https://www.cnblogs.com/tiancai/p/14025455.html
Copyright © 2011-2022 走看看