reentrantlock

AbstractQueuedSynchronizer在工具类Semaphore、CountDownLatch、ReentrantLock中的应用和CyclicBarrier

回眸只為那壹抹淺笑 提交于 2019-11-29 23:19:14
在上篇文章本人粗略地整理了AbstractQueuedSynchronizer和ReentrantLock的源码要点。其实,在java.util.concurrent包中,AbstractQueuedSynchronizer的应用非常广泛,而不局限于在ReentrantLock中的实现, 本文简要介绍下AbstractQueuedSynchronizer在Semaphore、ReentrantReadWriteLock等类中的应用 。 0. 回顾 上文在介绍AQS的时候,介绍了AQS和ReentrantLock类中的Sync子类互相配合完成可重入锁的实现,在这其中AQS所提供的是一套灵活和完整的队列处理机制。由于在AQS中已经提供了完整的队列处理机制,通常是不需要扩展的子类Override的。同时,AQS又提供了state属性和tryAcquire()/tryRelease()等方法,而这些正是需要子类根据具体的需求逻辑灵活实现的扩展点。从ReentrantLock、ReentrantReadWriteLock、Semaphore和CountDownLatch的实现来看,通常是在这些工具类的中封装实现自己独有的Sync内部类,而Sync就是对AQS的扩展实现。 1. Semaphore 学习操作系统理论课的时候,教材上应该都会讲过信号量这种概念,java.util

AQS的使用和reentrantlock

烈酒焚心 提交于 2019-11-29 20:59:32
AQS的使用和reentrantlock AQS概述 AQS是一个同步器,全称是AbstractQueuedSynchronizer类。 使用方法:子类继承AQS,然后重写tryAcquire、tryRelease、isHeldExclusively(如果是共享模式实现tryAcquireShared和tryReleaseShared方法),然后将其作为内部类,外部类定义unlock和lock方法并调用acquire和release方法即可(共享模式调用acquireShared和releaseShared)。 线程协调场景主要分为两类,一个线程在进行操作时不允许其他线程操作,即独占模式,还有允许多个线程操作的情况,称为共享模式。(独占和共享两种模式可以两个同时实现) 一个关键变量:内部封装了一个volatile修饰的int类型的字段state,代表当前同步状态。 定义了访问该字段的几个方法getState()、setState(val)、compareAndSetState(expect, update) 独占模式 独占模式下保证线程同步的操作是这样的,将state设为0,当某个线程要独占时都需要先判断state是不是0,如果不是就进入阻塞状态等待,如果是0就把state设置为1。然后进行操作,实现这个操作需要设置3种操作:分别是尝试获取同步状态、释放同步状态、判断是否有线程独占

关于ReentrantLock 中的lockInterruptibly方法的简单探究

冷暖自知 提交于 2019-11-29 20:04:44
今天在看Lock,都知道相比于synchronized,多了公平锁,可中断等优秀性能。 但是说到可中断这个特点,看到很多博客是这么描述的: “与synchronized关键字不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁会被释放” 我的理解是,应该是未获得到锁的线程被中断时,中断异常将会被抛出。 看了下lockInterruptibly()的源码 第一层 public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1);}第二层 public final void acquireInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (!tryAcquire(arg)) doAcquireInterruptibly(arg);} 第3层 private void doAcquireInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node

java锁的使用

不羁岁月 提交于 2019-11-29 16:26:30
1 synchronize和ReentrantLock synchronize锁是jvm内置的锁,它锁的是synchronize所在的类的对象,要同步那么就只能有一个对象。 ReentrantLock锁需要自己创建一个对象。 2 锁的使用 第一,提取出需要同步的模块; 第二,该模块作为一个类; 第三,以这个类作为锁对象synchronize,或者在这个类中创建一个ReentrantLock; 3 锁寄生于对象而存在 因为锁的使用需要内存,而要获取这样的内存需要创建一个对象,而创建对象要先设计一个类。所以,需要这样进行设计。 另外,把需要锁控制的资源抽象为一个对象也是模块化的需要。 来源: https://www.cnblogs.com/hustdc/p/11522442.html

CopyOnWriteArrayList源码分析

天大地大妈咪最大 提交于 2019-11-29 14:27:00
前言:CopyOnWriteArrayList为ArrayList的线程安全版本,这里来分析下其内部是如何实现的。 注:本文jdk源码版本为jdk1.8.0_172 1.CopyOnWriteArrayList介绍 CopyOnWriteArrayList是ArrayList的线程安全版本,因此其底层数据结构也是 数组 ,但是在写操作的时候都会拷贝一份数据进行修改,修改完后替换掉老数据,从而保证只阻塞写操作,读操作不会阻塞,实现读写分离。 1 public class CopyOnWriteArrayList<E> 2 implements List<E>, RandomAccess, Cloneable, java.io.Serializable {} 2.具体源码分析 底层数据结构: 1 /** The lock protecting all mutators */ 2 // 使用可重入锁进行加锁,保证线程安全 3 final transient ReentrantLock lock = new ReentrantLock(); 4 5 /** The array, accessed only via getArray/setArray. */ 6 // 底层数据结构,注意这里用volatile修饰,确定了多线程情况下的可见性 7 private transient

BlockingQueu 阻塞队列

孤街醉人 提交于 2019-11-29 13:37:41
java.util.concurrent public interface BlockingQueue<E> extends Queue<E> 简介 当阻塞队列插入数据时: 如果队列已经满了,线程则会阻塞等待队列中元素被取出后在插入。 当从阻塞队列中取数据时,如果队列是空的,则线程会阻塞等待队列中有新元素。 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列: 这两个附加的操作是: 在队列为空时,获取元素的线程会等待队列变为非空。 当队列满时,存储元素的线程会等待队列可用。 阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。 阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。 ArrayBlockingQueue : 一个由数组结构组成的有界阻塞队列(实现的接口是 BlockingQueue)。 LinkedBlockingQueue : 一个由链表结构组成的有界阻塞队列(实现的接口是 BlockingQueue)。 PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列(实现的接口是 BlockingQueue)。 DelayQueue: 一个使用优先级队列实现的无界阻塞队列(实现的接口是 BlockingQueue)。 SynchronousQueue:

ReentrantLock分析

点点圈 提交于 2019-11-29 11:46:14
主要分析下ReentrantLock锁的占用和释放过程。 一.几个核心变量 AbstractOwnableSynchronizer{ /** * 表示当前占有独占锁的线程,为null时说明锁未被占用 */ private transient Thread exclusiveOwnerThread; } AbstractQueuedSynchronizer extend AbstractOwnableSynchronizer{ private transient volatile Node head;//队列首节点 private transient volatile Node tail;//队列尾节点 private volatile int state;//同步状态,表示锁是否被占用。可重入锁,占用锁时继续获取锁,state=2 } /** waitStatus: *1:线程取消等待 *-1:后继节点的线程处于等待状态,需要当前结点唤醒 *-2:等待condition,condition.signale()唤醒,该线程会加入到队列中等待获取锁 *-3:下一次共享式同步状态获取将会被无条件地传播下去??没看懂 */ static final class Node { volatile int waitStatus;//当前线程的等待状态。状态被一个线程修改后,立即对其他线程可见

ReentrantLock分析

孤人 提交于 2019-11-29 10:45:14
主要分析下ReentrantLock锁的占用和释放过程。 一.几个核心变量 AbstractOwnableSynchronizer{ /** * 表示当前占有独占锁的线程,为null时说明锁未被占用 */ private transient Thread exclusiveOwnerThread; } AbstractQueuedSynchronizer extend AbstractOwnableSynchronizer{ private transient volatile Node head;//队列首节点 private transient volatile Node tail;//队列尾节点 private volatile int state;//同步状态,表示锁是否被占用。可重入锁,占用锁时继续获取锁,state=2 } /** * waitStatus: *1:线程取消等待 *-1:后继节点的线程处于等待状态,需要当前结点唤醒 *-2:等待condition,condition.signale()唤醒,该线程会加入到队列中等待获取锁 *-3:下一次共享式同步状态获取将会被无条件地传播下去??没看懂 */ static final class Node { volatile int waitStatus;//当前线程的等待状态。状态被一个线程修改后,立即对其他线程可见

Java5 多线程与TCP编程实践

不打扰是莪最后的温柔 提交于 2019-11-29 09:40:13
Java5 多线程与TCP编程实践 Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活。本文通过一个网络服务器模型,来实践Java5的多线程编程,该模型中使用了Java5中的线程池,阻塞队列,可重入锁等,还实践了Callable, Future等接口,并使用了Java 5的另外一个新特性泛型。 简介 本文将实现一个网络服务器模型,一旦有客户端连接到该服务器,则启动一个新线程为该连接服务,服务内容为往客户端输送一些字符信息。一个典型的网络服务器模型如下: 1. 建立监听端口。 2. 发现有新连接,接受连接,启动线程,执行服务线程。 3. 服务完毕,关闭线程。 这个模型在大部分情况下运行良好,但是需要频繁的处理用户请求而每次请求需要的服务又是简短的时候,系统会将大量的时间花费在线程的创建销毁。Java 5的线程池克服了这些缺点。通过对重用线程来执行多个任务,避免了频繁线程的创建与销毁开销,使得服务器的性能方面得到很大提高。因此,本文的网络服务器模型将如下: 1. 建立监听端口,创建线程池。 2. 发现有新连接,使用线程池来执行服务任务。 3. 服务完毕,释放线程到线程池。 下面详细介绍如何使用Java 5的concurrent包提供的API来实现该服务器。 初始化

Java5 多线程与TCP编程实践

冷暖自知 提交于 2019-11-29 09:39:00
Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活。本文通过一个网络服务器模型,来实践Java5的多线程编程,该模型中使用了Java5中的线程池,阻塞队列,可重入锁等,还实践了Callable, Future等接口,并使用了Java 5的另外一个新特性泛型。 简介 本文将实现一个网络服务器模型,一旦有客户端连接到该服务器,则启动一个新线程为该连接服务,服务内容为往客户端输送一些字符信息。一个典型的网络服务器模型如下: 1. 建立监听端口。 2. 发现有新连接,接受连接,启动线程,执行服务线程。 3. 服务完毕,关闭线程。 这个模型在大部分情况下运行良好,但是需要频繁的处理用户请求而每次请求需要的服务又是简短的时候,系统会将大量的时间花费在线程的创建销毁。Java 5的线程池克服了这些缺点。通过对重用线程来执行多个任务,避免了频繁线程的创建与销毁开销,使得服务器的性能方面得到很大提高。因此,本文的网络服务器模型将如下: 1. 建立监听端口,创建线程池。 2. 发现有新连接,使用线程池来执行服务任务。 3. 服务完毕,释放线程到线程池。 下面详细介绍如何使用Java 5的concurrent包提供的API来实现该服务器。 回页首 初始化 初始化包括创建线程池以及初始化监听端口