AQS同步队列器之一:介绍以及简单使用

一、简介

  JDK1.5之前都是通过synchronized关键字实现并发同步,而JDK1.5以后Doug Lea大师开发了current包下的类,通过JAVA代码实现了synchronized关键的语义。然而在current包下的这些类的实现大部分都不离不开一个基础组件----AQS(AbstractQueuedSynchronizer)也就是同步队列器。

  AQS定义了一套多线程访问共享资源的同步框架,比如ReentrantLock、CountDownLatch等都是依赖这个基础组件实现的。深入了解AQS有助于对Lock机制实现的原理理解,对并发又更加深入的认知。

二、简单使用示例

  在使用AQS基础组件前,先了解一下内部的基本接口。

    tryAcquire(int arg):独占式的获取同步状态,实现该方法需要查询当前状态并判断同步状态是否符合预期,然后通过CAS操作更改状态。

    tryRelease(int arg):释放同步状态,等待获取同步状态的线程将有机会获取释放的同步状态。

    tryAcquireShared(int arg):共享式的获取同步状态,返回大于0代表获取成功,否则就是获取失败。

    tryReleaseShared(int arg):共享式的释放同步状态。

    isHeldExclusively():判断当前的线程是否已经获取到了同步状态。

  在AQS的源码中,这些方法都是没有实现的,都是通过子类自己去实现。这也是AQS的设计核心模版模式的设计方式。通过接口也可以发现,AQS主要提供的就是相关于独占锁的获取释放以及共享锁的获取释放。

  通过AQS自定义实现锁的示例

 1 class  MyLock implements Lock{
 2
 3        private static class Sync extends AbstractQueuedSynchronizer{
 4
 5                 //是否处于占用状态
 6                 protected boolean isHeldExclusively(){
 7                       //当状态为1的时候代表为占用状态
 8                       return getState() == 1;
 9                 }
10                 //当状态为0时候获取锁
11                 public boolean tryAcquire(int acquire){
12                       if(compareAndSetState(0,1)){
13                                  setExclusiveOwnerThread(Thread.currentThread());//设置为当前线程拥有
14                               return true;
15                       }
16                       return false;
17                 }
18
19                 protected boolean tryRelease(int releases){
20                        if(getState() == 0){
21                             throw new IllegalMonitorStateException();
22                        }
23                        setExclusiveOwnerThread(null);//当前获取同步状态线程为null
24                        setState(0);//将状态设置为0
25                        return true;
26                }

实现AQS中定义的模版方法,通过CAS方法获取同步状态,如果内存中的同步状态与预期的状态值相同就用新值替换老值。当获取到了锁就将这个线程赋予这个锁。而tryRelease释放锁就是将当前锁线程赋予null,并将锁同步状态设置为0代表已经释放了这个锁。 

  上面的方法都是需要子类自己去实现的一些模版方法,而下面的这些方法就是实现自定义同步组件时将会调用的AQS中的实现方法。

    acquire(int arg):独占式的获取锁,如果当前线程获取同步状态成功,则由该方法返回,否则将会进入同步队列中等待

    acquireInterrupted(int arg):响应中断的获取锁,当前线程未获取同步状态而进入同步队列中,如果当前线程被中断,就会抛出InterruptedException并返回

    tryAcquireNanos(int arg,long nanos):在响应获取锁的基础上增加了超时获取锁的功能,如果在超时时间内获取到了锁就返回true,否则就返回false

    acquireShared(int arg):共享式的获取同步状态,如果当前线程未获取到同步状态将会进入同步队列等待,在同一时刻可以有多个线程可以获取锁状态

    acquireSharedInterrupted(int arg):响应中断的共享获取锁

    tryAcquiredSharedNanos(int arg,long nanos):超时获取共享锁

    release(int arg):独占式的获取同步状态,该方法会唤醒后继节点

    releaseShared(int arg):共享式的释放同步状态

 1          private  final  Sync  sync = new Sync();
 2          public void lock(){
 3              sync.acquire(1);//调用AQS中的acquire方法
 4          }
 5          public boolean tryLocK(){
 6              return sync.tryAcquire(1);//调用AQS中的tryLock方法
 7          }
 8          public void unlock(){
 9             sync.release();//调用AQS中的释放锁操作
10          }

怎么样评判是否已经获取锁是交由子类自己实现的,而锁获取以后的操作以及锁未被获取的操作都是AQS自己实现的。所以开发者关心的就是怎么样去评判线程是否获取到了锁。

三、总结 

   AQS在并发中是一个非常重要的基础类,它定义了很多同步组件需要的方法。通过这些方法开发者可以简单的实现一个相关的锁。

    

==================================================================================

不管岁月里经历多少辛酸和艰难,告诉自己风雨本身就是一种内涵,努力的面对,不过就是一场命运的漂流,既然在路上,那么目的地必然也就是前方。


==================================================================================

    

    

  

  

原文地址:https://www.cnblogs.com/wait-pigblog/p/9315700.html

时间: 2024-10-10 10:16:14

AQS同步队列器之一:介绍以及简单使用的相关文章

【Java并发编程实战】—– AQS(四):CLH同步队列

在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了头结点和尾节点,他们分别指向队列的头和尾,尝试获取锁.入队列.释放锁等实现都与头尾节点相关.而且每一个节点都引入前驱节点和后兴许节点的引用:在等待机制上由原来的自旋改成堵塞唤醒. 其结构例如以下: 知道其结构了,我们再看看他的实现.在线程获取锁时会调用AQS的acquire()方法.该方法第一次尝试获取锁假设

【死磕Java并发】-----J.U.C之AQS:CLH同步队列

此篇博客所有源码均来自JDK 1.8 在上篇博客[死磕Java并发]-–J.U.C之AQS:AQS简介中提到了AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一个FIFO双向队列,AQS依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态. 在CLH同步队列中,一个节点表示一个线程

消息队列介绍、RabbitMQ&Redis的重点介绍与简单应用

消息队列介绍.RabbitMQ.Redis 一.什么是消息队列 这个概念我们百度Google能查到一大堆文章,所以我就通俗的讲下消息队列的基本思路. 还记得原来写过Queue的文章,不管是线程queue还是进程queue他都是一种消息队列.他都是基于生产者消费者模型来处理消息. Python中的进程queue,是用于父进程与子进程,或者同属于一个父进程下的多个子进程之间进行信息交互.注意这种queue只能在同一个python程序下才能用,如果两个python程序,或者Python和别的什么程序,

[Java并发] AQS抽象队列同步器源码解析--锁获取过程

要深入了解java并发知识,AbstractQueuedSynchronizer(AQS)是必须要拿出来深入学习的,AQS可以说是贯穿了整个JUC并发包,例如ReentrantLock,CountDownLatch,CyclicBarrier等并发类都涉及到了AQS.接下来就对AQS的实现原理进行分析. 在开始分析之前,势必先将CLH同步队列了解一下 CLH同步队列 CLH自旋锁: CLH(Craig, Landin, and Hagersten locks): 是一个自旋锁,能确保无饥饿性,提

开源.net 混淆器ConfuserEx介绍

原文:开源.net 混淆器ConfuserEx介绍 今天给大家介绍一个开源.net混淆器——ConfuserEx http://yck1509.github.io/ConfuserEx/ 由于项目中要用到.net 混淆器,网上搜寻了很多款,比如Dotfuscator.xeoncode.foxit等等. 但大部分收费,当然也有破解版的,公司要求不能用盗版软件. 找了半天终于找到了ConfuserEX,用起来还行,就赶紧拿出来给大家分享下. 下载地址:https://github.com/yck15

Mahout in action 中文版-2.推荐器的介绍-2.1~2.2

2?推荐器的介绍 本章概要: ???????? Mahout中的推荐器 ?????????推荐器实战一瞥 ?????????推荐引擎精度与质量评估 ?????????基于一个真实数据集的测试:GroupLens 每天我们都会对一些喜欢的.不喜欢的甚至不关心的事物进行一些评价.这中行为往往是无意识的.你在收音机上听到一首歌,你可能会因为它的美妙或者难听而注意到它,也可能直接忽略.这样的情形也会非常普遍的发生在人们对于T恤.沙拉酱.滑雪场.发型.脸型或者电视节目. ???????? 尽管人们的口味多

阿里云开源离线同步工具DataX3.0介绍

阿里云开源离线同步工具DataX3.0介绍 一. DataX3.0概览 ? DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDFS.Hive.ODPS.HBase.FTP等各种异构数据源之间稳定高效的数据同步功能. 设计理念 为了解决异构数据源同步问题,DataX将复杂的网状的同步链路变成了星型数据链路,DataX作为中间传输载体负责连接各种数据源.当需要接入一个新的数据源的时候,只需要将此数据源对接到DataX,便能跟已有的数据源做到无缝数

【翻译】安卓新播放器EXOplayer介绍

http://developer.android.com/guide/topics/media/exoplayer.html ? 前言: Playing videos and music is a popular activity on Android devices. The Android framework provides?MediaPlayer?as a quick solution for playing media with minimal code, and the?MediaC

python3.4多线程实现同步的四种方式(锁机制、条件变量、信号量和同步队列)

临界资源即那些一次只能被一个线程访问的资源,典型例子就是打印机,它一次只能被一个程序用来执行打印功能,因为不能多个线程同时操作,而访问这部分资源的代码通常称之为临界区. threading的Lock类,用该类的acquire函数进行加锁,用realease函数进行解锁 import threading import time class Num: def __init__(self): self.num = 0 self.lock = threading.Lock() def add(self)