专栏首页JVMGCAQS同步队列结构分析
原创

AQS同步队列结构分析

同步队列结构

AQS使用的同步队列是基于一种CLH锁算法来实现。

CLH锁也是一种基于链表的可扩展、高性能、公平的自旋锁,申请线程只在本地变量上自旋,它不断轮询前驱的状态,如果发现前驱释放了锁就结束自旋.

img

同步器中包含了两个节点类型的引用,一个指向头节点(head),一个指向尾节点(tail),没有获取到锁的线程,加入到队列的过程必须保证线程安全,因此同步器提供了一个基于CAS的设置尾节点的方法CompareAndSetTail(Node expect,Node update),它需要传递当前线程认为的尾节点和当前节点,只有设置成功后,当前节点才能正式与之前的尾节点建立关联。

image-20210113202222401

同步器队列遵循FIFO,首节点是获取锁成功的节点,首节点的线程在释放锁时,会唤醒后续节点,而后继节点在成功获取到锁后,会把自己设置成首节点,设置首节点是由获取锁成功的线程来完成的,由于只有一个线程能成功获取到锁,所以设置首节点不需要CAS

image-20210113202940764

AQS实现一个线程安全的计数器

自定义互斥锁

package com.rumenz.task.aqs;


import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class MyLock {

    private static final Sync STATE_HOLDER = new Sync();

    /**
     * 通过Sync内部类来持有同步状态, 当状态为1表示锁被持有,0表示锁处于空闲状态
     */
    private static class Sync extends AbstractQueuedSynchronizer {

        /**
         * 是否被独占, 有两种表示方式
         *  1. 可以根据状态,state=1表示锁被占用,0表示空闲
         *  2. 可以根据当前独占锁的线程来判断,即getExclusiveOwnerThread()!=null 表示被独占
         */
        @Override
        protected boolean isHeldExclusively() {
            return getExclusiveOwnerThread() != null;
        }

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

        /**
         * 释放锁,将状态修改为0
         */
        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0) {
                throw new UnsupportedOperationException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

    }

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

    public void unlock() {
        STATE_HOLDER.release(1);
    }
}

测试案例

package com.rumenz.task.aqs;

import org.omg.Messaging.SYNC_WITH_TRANSPORT;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;


public class LockTest {
    private final static Integer clientTotal=100000;
    private final static Integer threadTotal=200;
    private static Count count=new Count();
    private static Count unSafe=new Count();

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
        final Semaphore semaphore=new Semaphore(threadTotal);

        for (int i = 0; i < clientTotal; i++) {

            executorService.execute(()->{
                try{
                    semaphore.acquire();
                    count.getIncrement();
                    unSafe.getUnSafeIncrement();
                    semaphore.release();

                }catch (Exception e){
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println("safe:"+count.getCount());
        System.out.println("unSafe:"+unSafe.getCount());
        executorService.shutdown();



    }


}

class Count{
    private MyLock myLock;
    private volatile int count;

     Count() {
        this.myLock=new MyLock();
    }

     int getCount(){
        return count;
    }
     int getIncrement(){
        myLock.lock();
        count++;
        myLock.unlock();
        return count;
    }
     int getUnSafeIncrement(){
        count++;
        return count;
    }
}

输出结果

safe:100000
unSafe:99995
wx.jpg

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • AQS(上) 同步队列AQS介绍篇

    AbstractQueuedSynchronizer抽象同步队列简称AQS,它是实现同步器的基础组件,并发包中锁的底层就是使用AQS实现的。另外,大多数开发者可...

    YanL
  • JUC解析-AQS-抽象队列同步器

    2.独占锁exclusive是一个悲观锁。保证只有一个线程经过一个阻塞点,只有一个线程可以获得锁。

    Java宝典
  • Java并发之-队列同步器AQS

    AQS是AbstractQueuedSynchronizer的简称,是用来构建锁或者其他同步组建的基础框架,它使用一个 int 类型的成员变量来表示同步状态,通...

    胖虎
  • 抽象同步队列AQS——AbstractQueuedSynchronizer锁详解

    谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!

    须臾之余
  • 【编程架构实战】——Java并发包基石-AQS详解

     Java并发包(JUC)中提供了很多并发工具,这其中,很多我们耳熟能详的并发工具,譬如ReentrangLock、Semaphore,它们的实现都用到了一个共...

    Java知音
  • 【编程架构实战】——Java并发包基石-AQS详解

     Java并发包(JUC)中提供了很多并发工具,这其中,很多我们耳熟能详的并发工具,譬如ReentrangLock、Semaphore,它们的实现都用到了一个共...

    Java知音
  • AQS 与 Sync 源码分析

    ReentrantReadWriteLock 源码分析 1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读...

    lwen
  • AQS 与 Sync 源码分析

    ReentrantReadWriteLock 源码分析 1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读...

    lwen
  • Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析

    在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concu...

    田小波
  • 高并发编程-AQS深入解析

    AbstractQueuedSynchronizer简称AQS,它是java.util.concurrent包下CountDownLatch/FutureTas...

    JavaQ
  • 「编程架构实战」——Java并发包基石-AQS详解

    protected int tryAcquireShared(int arg) :共享式获取同步状态,返回值大于等于0,代表获取成功;反之获取失败;

    Java知音
  • 从ReentrantLock的实现看AQS的原理及应用

    AQS作为JUC中构建锁或者其他同步组件的基础框架,应用范围十分广泛,这篇文章会带着大家从可重入锁一点点揭开AQS的神秘面纱。

    美团技术团队
  • AQS 锁核心类详解

    AQS(AbstractQuenedSynchronizer 抽象队列同步器) 是一个用来构建锁和同步器的框架,使用 AQS能简单且高效地构造出应用广泛的大量的...

    Java架构师必看
  • Java并发编程:AbstractQueuedSynchronizer的内部结构

      虽然已经有很多前辈已经分析过AbstractQueuedSynchronizer(简称AQS,也叫队列同步器)类,但是感觉那些点始终是别人的,看一遍甚至几遍...

    美的让人心动
  • 通过一个生活中的案例场景,揭开并发包底层AQS的神秘面纱

    当你在学习某一个技能的时候,是否曾有过这样的感觉,就是同一个技能点学完了之后,过了一段时间,如果你没有任何总结,或者是不经常回顾,遗忘的速度是非常之快的。

    用户1516716
  • 面试题:了解Java的AQS吗

    java.util.concurrent包(之后简称JUC包)中,提供了大量的同步与并发的工具类,是多线程编程的“利器”。其中locks包下,包含了多种锁,如R...

    用户1263954
  • 理解Java里面并发工具框架AbstractQueuedSynchronizer的底层实现

    前面的文章我们讨论了Java并发工具框架基类AbstractQueuedSynchronizer的核心功能和设计思想,本篇在结合源码来分析下相关的内容

    我是攻城师
  • 【Java源码】AQS 解析

    AQS 即 AbstractQueuedSynchronizer,是 java.util.concurrent.locks 包的一个重要概念。Java 中锁实现...

    程序员架构进阶
  • 【Java 源码解析】AQS

    AQS 即 AbstractQueuedSynchronizer,是 java.util.concurrent.locks 包的一个重要概念。Java 中锁实现...

    程序员架构进阶

扫码关注云+社区

领取腾讯云代金券