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
  • 相关阅读:
    javascript Ajax类
    C# 使注册表修改后立即生效
    MSSQL:创建临时表并赋值
    sql语句创建[表][列]带描述
    flash调用js中的方法,让js传递变量给flash (兼容 IE & FF)
    SQL中日期转换方法大全
    MSSQL:表变量的声明和赋值
    各种编程方面的CHM参考帮助手册(ADO参考手册、JavaScript参考手册、DHTML参考手册、TransactSQL参考手册、等等)
    vim命令的使用技巧
    Linux 如何启动mail邮件服务
  • 原文地址:https://www.cnblogs.com/tiancai/p/14025455.html
Copyright © 2011-2022 走看看