同步器

并发编程之AQS初探

回眸只為那壹抹淺笑 提交于 2019-12-15 10:54:56
Java并发编程核心在于java.concurrent.util包,而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这个行为的抽象就是基于AbstractQueuedSynchronizer,简称AQS。 AQS具备特性 •阻塞等待队列 •共享/独占 •公平/非公平 •可重入 •允许中断 可以说,AQS贯穿了整个并发包设计,是juc的核心,对于并发编程实现的理解至关重要。 AQS是什么 JDK源码对AQS有十分具体的解释,下面这段英文摘自java.util.concurrent.locks包下的AbstractQueuedSynchronizer.java源码文件。 * Provides a framework for implementing blocking locks and related * synchronizers ( semaphores , events , etc ) that rely on * first - in - first - out ( FIFO ) wait queues . This class is designed to * be a useful basis for most kinds of synchronizers that rely on a * single atomic

Java多线程进阶—— J.U.C之locks框架:AQS综述(1)

陌路散爱 提交于 2019-12-11 03:36:02
一、AQS简介 AbstractQueuedSynchronizer抽象类(以下简称AQS)是整个 java.util.concurrent 包的核心。在JDK1.5时,Doug Lea引入了J.U.C包,该包中的大多数同步器都是基于AQS来构建的。AQS框架提供了一套通用的机制来管理同步状态(synchronization state)、阻塞/唤醒线程、管理等待队列。 我们所熟知的ReentrantLock、CountDownLatch、CyclicBarrier等同步器,其实都是通过内部类实现了AQS框架暴露的API,以此实现各类同步器功能。这些同步器的主要区别其实就是对同步状态(synchronization state)的定义不同。 AQS框架,分离了构建同步器时的一系列关注点,它的所有操作都围绕着资源——同步状态(synchronization state)来展开,并替用户解决了如下问题: 资源是可以被同时访问?还是在同一时间只能被一个线程访问?(共享/独占功能) 访问资源的线程如何进行并发管理?(等待队列) 如果线程等不及资源了,如何从等待队列退出?(超时/中断) 这其实是一种典型的模板方法设计模式: 父类(AQS框架)定义好骨架和内部操作细节,具体规则由子类去实现 。 AQS框架将剩下的一个问题留给用户: 什么是资源?如何定义资源是否可以被访问?

Java并发面试问题,谈谈你对AQS的理解

我只是一个虾纸丫 提交于 2019-12-10 16:45:30
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 一、概述 谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)! 类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch...。 以下是本文的目录大纲: 概述 框架 源码详解 简单应用 二、框架 它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。这里volatile是核心关键词,具体volatile的语义,在此不述。state的访问方式有三种: getState() setState() compareAndSetState() AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行

初识Lock与AbstractQueuedSynchronizer(AQS)

别等时光非礼了梦想. 提交于 2019-12-04 20:36:10
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 1. concurrent包的结构层次 在针对并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,针对这些代码进行研究会让我们队并发编程的掌握更加透彻也会大大提升我们队并发编程技术的热爱。这些代码在java.util.concurrent包下。如下图,即为concurrent包的目录结构图。 其中包含了两个子包:atomic以及lock,另外在concurrent下的阻塞队列以及executors,这些就是concurrent包中的精华,之后会一一进行学习。而这些类的实现主要是依赖于volatile以及CAS(关于volatile可以看 这篇文章 ,关于CAS可以看 这篇文章的3.1节 ),从整体上来看concurrent包的整体实现图如下图所示: 2. lock简介 我们下来看concurent包下的lock子包。锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。在Lock接口出现之前

Java多线程

坚强是说给别人听的谎言 提交于 2019-12-04 11:53:55
1. 多线程 image.png 新建状态: 一个新产生的线程从新状态开始了它的生命周期。它保持这个状态直到程序 start 这个线程。 运行状态:当一个新状态的线程被 start 以后,线程就变成可运行状态,一个线程在此状态下被认为是开始执行其任务 就绪状态:当一个线程等待另外一个线程执行一个任务的时候,该线程就进入就绪状态。当另一个线程给就绪状态的线程发送信号时,该线程才重新切换到运行状态。 休眠状态: 由于一个线程的时间片用完了,该线程从运行状态进入休眠状态。当时间间隔到期或者等待的时间发生了,该状态的线程切换到运行状态。 终止状态: 一个运行状态的线程完成任务或者其他终止条件发生,该线程就切换到终止状态。 2. 僵死进程 计算机的计算模型大部分是基于空间和时间来考虑的。僵死进程唯一占用的空间是pid空间,这个空间如果不能合理的应用就会造成浪费,之所以保留这个空间,是为了让父进程感知子进程已经终止这个行为。时间方面,这个感知过程是一个异步的过程。 3. 创建线程的方式 继承 Thread 类 实现 Runnable 接口 使用 Executor 框架 法一:继承Thread类 1.1定义一个类继承Thread 1.2重写run方法 1.3创建对象 1.4调用start方法开启线程 线程对象调用run()方法和start()方法区别? 调用run方法不开启线程,仅是对象调用方法

AQS 抽象队列同步器(Abstract Queued Synchronizer) 知识点

僤鯓⒐⒋嵵緔 提交于 2019-12-03 13:32:18
AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态。 AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁。它提供了三个方法(getState()、setState(int newState)、compareAndSetState(int expect,int update))来对同步状态state进行操作,当然AQS可以确保对state的操作是安全的。 AQS通过内置的FIFO同步队列来完成资源获取线程的排队工作,如果当前线程获取同步状态失败(锁)时,AQS则会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,则会把节点中的线程唤醒,使其再次尝试获取同步状态。 出处: https://juejin.im/entry/5ae02a7c6fb9a07ac76e7b70 来源: https://www.cnblogs.com/cag2050/p/11797186.html

AQS(抽象队列同步器)

一个人想着一个人 提交于 2019-12-02 15:44:27
   AQS(全称为AbstractQueuedSynchronizer),即抽象队列同步器 ,它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列。   state的访问方式有:getState();  setState();  CompareAndState()       AQS定义两种资源共享方式:     Exclusive独享资源,只有一个线程能执行,如reentrantlock(重入锁)     Share共享资源,多个线程可同时执行,如Semaphore(信号量)/countdownlatch(闭锁)    AQS只是一个框架,定义了一个接口,具体资源的获取/释放方式交由自定义同步器去实现(通过state的get/set/CAS) 。之所以没有定义成abstract,是因为独占模式下只用实现tryAcquire/tryRelease,而共享模式下只用实现tryAcquireShared/tryReleaseShared。如果都定义成abstract,那么每个模式也要去实现另一个模式下的接口。不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,具体线程等待队列的维护,AQS已经在顶层实现好了。    自定义同步器主要实现方法:     1

AQS(队列同步器)

纵然是瞬间 提交于 2019-12-01 10:24:05
目录导引 :   一、简介   二、源码解析(JDK8)   三、运用示例 一、简介   1、volatile    volatile修饰的共享变量可以保证可见性和有序性(禁止指令重排序)。    2、CAS:   CAS的原理很简单,包含三个值当前内存值(V)、预期原来的值(A)以及期待更新的值(B),   如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B,返回true。否则处理器不做任何操作,返回false。   要实现这个需求,java中提供了Unsafe类,它提供了三个函数,分别用来操作基本类型int和long,以及引用类型Object public final native boolean compareAndSwapObject (Object obj, long valueOffset, Object expect, Object update); public final native boolean compareAndSwapInt (Object obj, long valueOffset, int expect, int update); public final native boolean compareAndSwapLong (Object obj, long valueOffset, long expect, long

concurrent包的同步器

梦想与她 提交于 2019-12-01 04:44:55
concurrent包的同步器:CountDownLatch、CyclicBarrier、Semaphore 同步器简介 名称 功能 构成 主要方法 CountDownLatch(闭锁) 一个线程等待其它线程完成各自工作后在执行 继承aqs await()/countDown() CyclicBarrier (循环屏障) 一组线程协同工作 ReentrantLock await() Semaphore(信号) 控制同时访问特定资源的线程数量 继承aqs acquire()/release() CountDownLatch(闭锁) 一个线程等待其它线程完成各自工作后在执行。例如:主线程希望复制启动框架服务的线程已经启动索引的框架服务在执行。 例如:主线程希望复制启动框架服务的线程已经启动索引的框架服务在执行。 开始执行前等待n个线程完成各自任务。 死锁检测 核心源码 public class CountDownLatch { /** * Synchronization control For CountDownLatch. * Uses AQS state to represent count. */ private static final class Sync extends AbstractQueuedSynchronizer { private static final

同步器

≡放荡痞女 提交于 2019-11-30 11:59:20
版权声明:本文为博主转载文章 原文链接: https://blog.csdn.net/lixiaobuaa/article/details/78995572 线程之间相互合作时,需要用到同步器来完成同步,下面介绍几种常用同步器: 1.Semaphore(信号量) 信号量数量限制了访问资源的线程总数,线程请求会消耗一个信号量,当信号量为0时,新的线程会阻塞,直到有线程释放了一个信号量 线程类: package Semaphore; import java.util.concurrent.Semaphore; public class SemaphoreThread extends Thread { Semaphore semaphore; public SemaphoreThread (Semaphore semaphore){ this .semaphore = semaphore; } @Override public void run () { try { semaphore.acquire(); System.out.println( "一个线程正在执行" ); sleep( 3000 ); System.out.println( "一个线程结束运行" ); } catch (InterruptedException e) { e.printStackTrace(); }