09-Java多线程-5、AQS-基于AQS实现自定义锁

并发编程 专栏收录该内容
33 篇文章 0 订阅

一、自定义锁

  • ASQ设计是为了简化并发工具的实现,里面实现了大量线程状态的维护,线程间的同步等待通知等细节,java并发的锁等很多基础组件都是基于AQS来实现的,因此可以通过AQS来自定义实现锁,在AQS类的注释上我们可以看到作者Doug Lea下面一段话,具
    体真的推荐去看看源码中的英文注释,非常多的注释对理解和使用AQS都很有帮助,读起来吃力可以直接谷歌翻译。

   Provides a framework for implementing blocking locks and related
   synchronizers (semaphores, events, etc) that rely on
   first-in-first-out (FIFO) wait queues. 
   提供一个基于FIFO等待队列的框架来实现阻塞锁和相关的同步器(semaphores, events,等)
   
   This class is designed to be a useful basis for most kinds of synchronizers that rely on a
   single atomic {@code int} value to represent state.
   这个类基于一个原子变量来表示状态,并设计成一个对于大多与同步器有用的基础组件。
   
   
   Subclasses must define the protected methods that change this state, and which
   define what that state means in terms of this object being acquired or released. 
   子类必须定义那些改变state状态的protected方法,子类应该定义对象获得或者释放states状态的含义。
   (这里不太好翻译和理解,意思就是子类需要重写对应的protected方法,在方法里面会改变states状态,我们
   需要描述出获得或者释放states的含义,,大概这么理解吧。)
   
   
   Given these, the other methods in this class carry out all queuing and blocking mechanics. 
   基于这些,AQS类里面的其他方法会实现队列和阻塞机制。

  Subclasses should be defined as non-public internal helper
  classes that are used to implement the synchronization properties
  of their enclosing class.
  子类应该定义一个非公开的内部帮助类来协助外部类实现同步属性。
  
  • 本文基于AQS实现一个互斥锁。在JDK中基于AQS实现了很多锁和同步工具类,如CountDownLatch,ReentrantLock,ReentrantReadWriteLock、Semaphore,可以参照我之前的分析文章。

二、代码

public class MyLock implements Lock {

    /**
     * 这是内部类,内部类继承ASQ,重写ASQ中获取同步状态的几个方法(因为是实现排它锁,重写阻塞模式的方法即可)
     */
    private static class Sync extends AbstractQueuedSynchronizer {

        /**
         * state 表示获取到锁 state=1 获取到了锁,state=0,表示这个锁当前没有线程拿到
         */
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        /**
         * 尝试获取锁,将状态从0修改为1,修改成功则将自身线程设置为当前拥有锁的线程
         */
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        /**
         * 释放锁,将状态修改为0,因为只有一个线程持有锁,因此不需要CAS,是线程安全的
         */
        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0) {
                throw new UnsupportedOperationException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        Condition newCondition() {
            return sync.newCondition();
        }
    }

    private static final Sync sync = new Sync();

    /**
     * 下面的实现Lock接口需要重写的方法,基本是就是调用内部内Sync的方法
     */
    @Override
    public void lock() {
        //加锁
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        //加锁,可响应中断
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        //尝试加锁
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        //加锁,可超时
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        //解锁
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        //获取Condition对象
        return sync.newCondition();
    }
}

三、测试

  • 我们定义了10个线程,所有线程共用一把锁,预期线程会同步依次执行打印。
public class MyLockTest {

    private static Lock lock = new MyLock();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new MyThread(lock, "Thread-" + i).start();
        }
    }

    static class MyThread extends Thread {

        Lock lock;

        public MyThread(Lock lock, String name) {
            super(name);
            this.lock = lock;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                System.out.println("Thread " + Thread.currentThread().getName() + " do something thing..." +  new Date());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

四、输出

  • 我们看到所有的线程排队输出,每一秒输出一次,说明我们的锁机制生效了
Thread Thread-0 do something thing...Mon Apr 29 19:16:57 CST 2019
Thread Thread-1 do something thing...Mon Apr 29 19:16:58 CST 2019
Thread Thread-2 do something thing...Mon Apr 29 19:16:59 CST 2019
Thread Thread-4 do something thing...Mon Apr 29 19:17:00 CST 2019
Thread Thread-5 do something thing...Mon Apr 29 19:17:01 CST 2019
Thread Thread-6 do something thing...Mon Apr 29 19:17:02 CST 2019
Thread Thread-3 do something thing...Mon Apr 29 19:17:03 CST 2019
Thread Thread-7 do something thing...Mon Apr 29 19:17:04 CST 2019
Thread Thread-8 do something thing...Mon Apr 29 19:17:05 CST 2019
Thread Thread-9 do something thing...Mon Apr 29 19:17:06 CST 2019
  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

<p><strong><span style="color: #337fe5;">[JAVA工程师必会知识点之并发编程]</span></strong></p> <p style="font-size: 14px; background-color: #ffffff;"> </p> <p style="color: #008781;"> </p> <p class="ql-long-24357476" style="color: #222226; font-family: "font-size:14px; background-color: #ffffff;"> </p> <p class="MsoNormal"><strong><span style="color: #000000;">1现在几乎</span><span style="color: #000000;">100%</span><span style="color: #000000;">的公司面试都必须面试并发编程,尤其是互联网公司,对于并发编程的要求更高,并发编程能力已经成为职场敲门砖。</span></strong></p> <p class="MsoNormal"><strong><span style="color: #000000;">2</span><span style="color: #000000;">现在已经是移动互联和大数据时代,对于应用程序的性能处理能力处理时效性要求更高了,传统的串行化编程无法充分利用现有的服务器性能。</span></strong></p> <p class="MsoNormal"><strong><span style="color: #000000;">3</span><span style="color: #000000;">并发编程是几乎所有框架的底层基础,掌握好并发编程更有利于我们学习各种框架。想要让自己的程序执行接口响应批处理效率更高,必须使用并发编程。</span></strong></p> <p class="MsoNormal"><strong><span style="color: #000000;">4并发编程是中高级程序员的标配,是拿高薪的必备条件。</span></strong></p> <p> </p> <p><span style="color: #337fe5;">【主讲讲师】</span></p> <p><span style="color: #337fe5;"><span style="color: #000000;">尹洪亮Kevin:</span><br /><span style="color: #000000;">现任职某互联网公司首席架构师,负责系统架构项目群管理产品研发工作。</span><br /><span style="color: #000000;">10余年软件行业经验,具有数百个线上项目实战经验。</span><br /><span style="color: #000000;">擅长JAVA技术栈高并发高可用伸缩式微服务架构DevOps。</span><br /><span style="color: #000000;">主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行</span><br /><br /></span></p> <p style="color: #008781;"><strong><span style="color: #337fe5;">【推荐你学习这门课的理由:</span><span style="color: #e53333;">知识体系完整+丰富学习资料】</span></strong></p> <p style="margin-left: 18pt; text-indent: -18pt; background: white;">1<span style="color: #000000;"> 本课程总计122课时,由五大体系组成,目的是让你一次性搞定并发编程。分别是并发编程基础进阶精通篇Disruptor高并发框架RateLimiter高并发访问限流吗,BAT员工也在学。</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">2课程附带附带3个项目源码,几百个课程示例,5个高清PDF课件。</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">3本课程0基础入门,从进程线程JVM开始讲起,每一个章节只专注于一个知识点,每个章节均有代码实例。</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;"> </span></p> <p style="color: #008781; background: white;"><span style="color: #337fe5;">【课程分为基础篇进阶篇高级篇】</span></p> <p style="color: #008781; background: white;"><span style="color: #337fe5;">一基础篇<br /></span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">基础篇从进程与线程内存CPU时间片轮训讲起,包含线程的3种创建方法可视化观察线程joinsleepyieldinterrupt,Synchronized重入对象waitnotify线程上下文切换守护线程阻塞式安全队列等内容。</span></p> <p style="color: #008781; background: white;"><span style="color: #337fe5;">二进阶篇</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">进阶篇课程涵盖volatied关键字Actomic类可见性原子性ThreadLocalUnsafe底层同步类容器并发类容器5种并发队列COW容器InheritableThreadLocal源码解析等内容。</span></p> <p style="color: #008781; background: white;"><span style="color: #337fe5;">三精通篇</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">精通篇课程涵盖JUC下的核心工具类,CountDownLathCyclicBarrierPhaserSemaphoreExchangerReentrantLockReentrantReadWriteLockStampedLockLockSupportAQS底层悲观乐观自旋公平非公平排它共享重入线程池CachedThreadPoolFixedThreadPoolScheduledThreadPoolSingleThreadExecutor自定义线程池ThreadFactory线程池切面编程线程池动态管理等内容,高并发设计模式,Future模式Master Worker模式CompletionServiceForkJoin等</span></p> <p style="color: #008781; background: white;"><span style="color: #337fe5;">课程中还包含</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">Disruptor高并发无框架讲解:Disruptor支持每秒600万订单处理的恐怖能力。深入到底层原理和开发模式,让你又懂又会用。</span></p> <p style="color: #008781; background: white;"><span style="color: #000000;">高并发访问限流讲解:涵盖木桶算法令牌桶算法Google RateLimiter限流开发Apache JMeter压力测试实战。</span></p> <p> </p> <p class="ql-long-24357476" style="color: #222226; font-family: "font-size:14px; background-color: #ffffff;"><strong><span style="color: #337fe5;">【学完后我将达到什么水平?】</span></strong></p> <p class="ql-long-24357476" style="color: #222226; font-family: "font-size:14px; background-color: #ffffff;"><span style="color: #000000; font-family: ";">1 吊打一切并发编程相关的笔试题面试题。</span></p> <p class="ql-long-24357476" style="color: #222226; font-family: "font-size:14px; background-color: #ffffff;"><span style="color: #000000; font-family: ";">2 重构自己并发编程的体系知识,不再谈并发色变。</span></p> <p class="ql-long-24357476" style="color: #222226; font-family: "font-size:14px; background-color: #ffffff;"><span style="color: #000000; font-family: ";">3 精准掌握</span><span style="color: #000000; font-family: ";">JAVA</span><span style="color: #000000; font-family: ";">各种并发工具类方法关键字的原理和使用。</span></p> <p class="ql-long-24357476" style="color: #222226; font-family: "font-size:14px; background-color: #ffffff;"><span style="color: #000000; font-family: ";">4 轻松上手写出更高效更优雅的并发程序,在工作中能够提出更多的解决方案。</span></p> <p class="MsoNoSpacing" style="margin-left: 18pt; text-indent: -18pt;"><span style="color: #000000;"> </span></p> <p class="MsoListParagraph" style="margin-left: 18.0pt; text-indent: -18.0pt;"> </p> <p> </p> <p class="ql-long-24357476" style="color: #008781;"> </p> <p class="MsoListParagraph" style="color: #008781; margin-left: 36pt; text-indent: -36pt;" align="left"><strong><span style="color: #337fe5;">【</span><span style="color: #337fe5;">面向人群</span><span style="color: #337fe5;">】</span></strong></p> <p class="MsoListParagraph" style="color: #008781; margin-left: 36pt; text-indent: -36pt;" align="left"><span style="color: #000000;">1 总感觉并发编程很难很复杂不敢学习的人群。</span></p> <p class="MsoListParagraph" style="color: #008781; margin-left: 36pt; text-indent: -36pt;" align="left"><span style="color: #000000;">2 准备跳槽找工作拿高薪的程序员。</span></p> <p class="MsoListParagraph" style="color: #008781; margin-left: 36pt; text-indent: -36pt;" align="left"><span style="color: #000000;">3 希望提高自己的编程能力,开发出更高效性能更强劲系统的人群。</span></p> <p class="MsoListParagraph" style="color: #008781; margin-left: 36pt; text-indent: -36pt;" align="left"><span style="color: #000000;">4 想要快速系统化精准掌握并发编程的人群。</span></p> <p class="MsoListParagraph" style="color: #008781; margin-left: 18pt; text-indent: -18pt;"><strong>【课程知识体系图】</strong></p> <p class="MsoListParagraph" style="color: #008781; margin-left: 18pt; text-indent: -18pt;"><img src="https://img-bss.csdnimg.cn/202007100721287398.png" alt="" /></p>
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值