AbstractQueuedSynchronizer(AQS)同步器

1. AQS基本属性

  1. CAS算法:
    CAS, CPU指令,在大多数处理器架构,包括IA32、Space中采用的都是CAS指令,CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
  2. 核心接口:
    getState()
    setState()
    compareAndSetState()
    isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
    tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
    tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
    tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
    tryReleaseShared(int):共享方式。尝试释放资源,成功则返回true,失败则返回false。
  1. 状态位

    private volatile int state;
    获得锁标识,通过调用Unsafe.compareAndSwapInt()实现。

  2. 获得锁的线程

    private transient Thread exclusiveOwnerThread;

2. ReentrantLock

1. 非公平锁
  1. lock()

    1. 首先尝试把state由0置为1,如果成功把当前线程标记为exclusiveOwnerThread,如果失败进入2
    2. 当前线程形成Node对象,然后链至链表结尾。尝试获得锁,不成功阻塞(LockSupport.park(Thread),调用Unsafe.park())
  2. unlock()

    找到链表的head,head是个空的Node,其next指向链表中第一个等待的线程,然后唤醒此线程(LockSupport.unpark(Thread),调用Unsafe.unpark())

默认情况下ReentrantLock为非公平锁,其原因有如下三条:

  1. 新的线程上来就尝试获得锁,有可能会获取成功,导致等待时间长的线程没有先执行。
  2. 新线程在第一次尝试获得锁失败后,在进入链表之前又尝试获得锁,有可能导致新线程提前执行。
  3. 线程被唤醒后尝试获得锁,有可能失败,导致被延迟执行。

2. 公平锁

与非公平锁最大的区别是当尝试获得锁时会先判断链表中是否有排队的线程,如果没有再尝试获得锁,这样可以保证按照链表的顺序执行线程,保证了一种公平。

原文地址:http://blog.51cto.com/wenshengzhu/2349265

时间: 2024-11-13 09:40:52

AbstractQueuedSynchronizer(AQS)同步器的相关文章

4.从AbstractQueuedSynchronizer(AQS)说起(3)——AQS结语

前两节的内容<2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放> .<3.从AbstractQueuedSynchronizer(AQS)说起(2)——共享模式的锁获取与释放>对AQS同步器已经有了一个大致的了解,从独占模式和共享模式来解析了AQS的两个基本方面,一个是同步状态的获取,另外一个是同步状态的释放,这是AQS最基本的特性,前面两节都是以阻塞的形式获取同步状态,但实际上AQS还能超时等待获取同步状态,或者非阻塞的方式

AbstractQueuedSynchronizer AQS框架源码剖析

目录 1.引子 2.AQS架构设计原理 3.AQS源码实现 4.简单应用 5.总结 ====正文分割线============ 一.引子 Doug Lea在JSR166中建立了一个小框架,AbstractQueuedSynchronizer同步器框架(AQS).这个框架为构造同步器提供一种通用的机制,并且被j.u.c包中大部分类使用. 包结构如下图,其中AbstractOwnableSynchronizer是其父类,而AbstractQueuedLongSynchronizer是其32位状态的升

JUC回顾之-AQS同步器的实现原理

1.什么是AQS? AQS的核心思想是基于volatile int state这样的volatile变量,配合Unsafe工具对其原子性的操作来实现对当前锁状态进行修改.同步器内部依赖一个FIFO的双向队列来完成资源获取线程的排队工作. 2.同步器的应用 同步器主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态,对同步状态的修改或者访问主要通过同步器提供的3个方法: getState() 获取当前的同步状态 setState(int newState) 设置当前同步状态 co

AbstractQueuedSynchronizer(AQS)源码解析(一)

在JDK1.5版本,新增了并发包,其中包含了显示锁.并发容器.在这些锁和容器里,都有同步器(AQS)的身影.为了更好地理解JDK的并发包,我会用三个主题来详细描述AbstractQueuedSynchronizer的实现. 在AQS中,涉及到同步队列以及Condition对象,这也是我为什么要用三个主题来讲述的原因.本节将主要讲述同步队列,后面两节会分别讲述Condition对象以及AQS的主要功能实现. AQS同步队列的主要功能是将无法获得资源的线程放入同步队列中,进行等待,它是通过链表来

Java并发之AQS同步器学习

AQS队列同步器学习 在学习并发的时候,我们一定会接触到 JUC 当中的工具,JUC 当中为我们准备了很多在并发中需要用到的东西,但是它们都是基于AQS(AbstractQueuedSynchronizer)队列同步器来实现的,也就是我们如果能够去梳理清楚AQS当中的知识点,对我们以后了解其他并发功能键有很大的帮助. CLH队列 队列同步器(AbstractQueuedSynchronizer),是用来构建锁或者其他同步组件的基础框架,它使用了一个int变量来表示同步状态,通过内置的FIFO队列

Java并发编程原理 - Unsafe &amp;&amp; LockSupport类及AQS同步器的设计

[相关源码] (https://github.com/Wasabi1234/Java-Concurrency-Progamming-Tutorial) 1 Unsafe类的park和unpark public native void park(boolean var1, long var2); public native void unpark(Object var1); park方法用来阻塞一个线程,第一个参数用来指示后面的参数是绝对时间还是相对时间,true表示绝对时间,false表示从此刻

8.初识Lock与AbstractQueuedSynchronizer(AQS)

1. concurrent包的结构层次 在针对并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,针对这些代码进行研究会让我们对并发编程的掌握更加透彻也会大大提升我们队并发编程技术的热爱.这些代码在java.util.concurrent包下.如下图,即为concurrent包的目录结构图. 其中包含了两个子包:atomic以及lock,另外在concurrent下的阻塞队列以及executors,这些就是concurrent包中的精华,之后会一一进行学习.而这些类的实现主要是

Java 并发之AbstractQueuedSynchronizer(AQS)源码解析

关键字:CLH,Node,线程,waitStatus,CAS,中断 目录 图解AQS的操作细节 0.前言 1.基本概念 1.1.CAS自旋 1.2.Node 1.3.CLH & AQS 1.4.ReentrantLock 2.图解AQS 2.1.线程A单独运行 2.2.线程B开始运行 2.3.线程C开始运行 2.4.线程A停止运行,线程B继续运行 2.5.1.线程B停止运行,线程C继续运行 2.5.2.线程C放弃竞争 3.问题总结 3.1.为什么在unparkSuccessor操作中从尾节点开始

Java并非锁之独占非公平锁理解

Java锁系列教程之独占式锁 在Java并发编程中,锁是一个很重要的对象.Java中锁有两种:隐式锁和显式锁.使用synchronized关键字的锁是隐式锁.因为锁的申请和释放都是由JVM来维护的,不用我们来手动处理.使用Java并发包locks包下的锁,需要使用者手动申请和手动关闭.这种形式是显式锁.如果按照多个线程能不能共享同一个锁(资源)来分的话,可以分为独占式(排他)锁和共享锁.其中synchronized关键字的锁和ReentrantLock锁的锁都是独占式锁. 通过前面三篇文章的学习