5.0抽象队列同步器AQS引用Lock详解

5.抽象队列同步器AQS引用Lock详解

0.前序

​ 说起并发锁Lock,我们肯定就想起了Doug Lea,[美国国籍,现担任[纽约州立大学]Oswego分校教师 。Doug Lea 在Java发展过程中扮演了举足轻重的角色, Tiger广纳了15项JSRs(Java Specification Requests)的语法及标准,其中一项便是JSR-166。JSR-166是来自于Doug编写的util.concurrent包。

​ Java并发编程核心在于iava.util.concurrent包而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这个行为的抽象就是基于AbstractQueuedSynchronizer简称AQS,AQS定义了一套多线程访问共享资源的同步器框架,是一个依赖状态(state)的同步器。

0.1Lock总体介绍

在这里插入图片描述
从上面的图可知ReentrantLock是基于AQS实现的,具有可重入和公平性的特点;我们思考下用伪代码写下Lock锁的实现:

//多个争取锁,一个成功其他等待,需要一个无尽的循环--自旋
for(;;){  //while(true)
    if(获取锁){//CAS算法加锁
        break;//跳出循环
    }
    Thread.yeild();//让出CPU使用权其他的线程或Thread.sleep();
    //
    HeadSet,LinkedQueued();
    put(Thread);
    LockSupport.park();//阻塞
}

大致的逻辑是:必须有一个循环一直的可以让多个线程获取锁,一个获取成功,其他的线程阻塞等待,直到那个释放锁;

0.2CAS算法知识扩展

​ CAS是一个算法逻辑:例如两个线程同时更新一个变量,两个线程的工作内存中都有一个变量的副本,当要修改变量值时,会先和主内存中的变量做比较如果副本中的值和主内存中的值一样,就更新,如果不一样重新获取变量值,在更新;先比较再交换,两个操作组成的原子操作。

总结:LOCK 核心功能:自旋(循环),cas算法加锁,LocksSouport(阻塞和唤醒) ,队列(公平锁和非公平锁)

1.ReentrantLock

ReentrantLock是一种基干AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全,而目它具有比synchronized更多的特性,比如它支持手动加锁与解锁,支持加锁的公平性。

//使用ReentrantLock进行同步
ReentrantLock lock =new ReentrantLock(false);//false为非公平锁,true为公平锁 
lock.lock()//加锁 
lock.unlock()//解锁s

ReentrantLock如何实现synchronized不具备的公平与非公平性呢?
在ReentrantLock内部定义了一个Sync的内部类,该类继承AbstractQueuedSynchronized,对该抽象类的部分方法做了实现;并且还定义了两个子类
1)FairSync 公平锁的实现
2)NonfairSync非公平锁的实现
这两个类都继承自Sync,也就是间接继承了AbstractQueuedSynchronized,所以这一个ReentrantLock同时具备公平与非公平特性。上面主要涉及的设计模式:模板模式-子类根据需要做具体业务实现 AOS具备特性

2.AQS具备特性
  • 阻塞等待队列
  • 共享/独占
  • 公平/非公平
  • 可重入
  • 允许中断

除了Lock外,Java.util.concurrent当中同步器的实现如LatchBarrier,BlockingQueue等,都是基于AQS框架实现

  • 一般通过定义内部类Sync继承AQS

  • 将同步器所有调用都映射到Sync对应的方法

AQS内部维护属性volatile int state(32位)

  • state表示资源的可用状态

State三种访问方式:getState()、setState()、compareAndSetState()

AQS定义两种资源共享方式

1)Exclusive-独占,只有一个线程能执行,如ReentrantLock
2)Share-共享,多个线程可以同时执行,如Semaphore/CountDownLatch

2.1AQS定义两种队列
  • 同步等待队列
  • 条件等待队列

不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。

自定义同步器实现时主要实现以下几种方法:。

  • isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它

  • tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。

  • tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。

  • tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源

  • tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false

2.1.1同步等待队列

AQS当中的同步等待队列也称CLH队列,CLH队列是Craig、Landin、Hagersten三人发明的一种基于双向链表数据结构的队列,是FIFO先入先出线程等待队列,Java中的CLH队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苹水相峰

你的打赏是对我最大的肯定

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值