• 使用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
  • 相关阅读:
    利用百度地图API实现百度地图坐标拾取
    newtonsoft.json的JObject里的JSON数据 动态
    监听微信返回按钮
    C# 如何理解如下泛型约束 class A<T>:where T:class{}
    微博数据库设计 _转
    新浪微博,腾讯微博mysql数据库主表猜想 __转
    Ferris教程学习笔记:js示例3.9 倒计时时钟
    Ferris教程学习笔记:js示例3.8 简易网页时钟
    Ferris教程学习笔记:js示例3.6 判断数字是否为两位数
    Ferris教程学习笔记:js示例3.5 页面加载后累加,自加1
  • 原文地址:https://www.cnblogs.com/tiancai/p/14025455.html
Copyright © 2020-2023  润新知