reentrantlock

手写一个ReentrantLock锁

China☆狼群 提交于 2020-02-01 19:53:06
手写ReentrantLock 最近学习了Java语言中锁相关知识,看了一下 ReentrantLock 源码,自己手写了一个 ReentrantLock 。 ReentrantLock 是一个可重入锁,并且在源码中通过构造函数可以使其在公平锁和非公平锁之间转换。 可重入锁即当前线程可以在不释放锁的情况下多次获取锁,但是释放锁的次数应与获取锁的次数相同,否则会抛出 IllegalMonitorStateException 异常。 公平锁和非公平锁的区别在与,公平锁使先进入等待队列的线程先获取锁,每个线程都有机会获取锁。非公平锁则是每个线程获取锁的几率不确定,非公平锁并发性较好,但容易造成某些线程长时间获取不到锁。 不可重入ReentrantLock,非公平 /** * 不可重入锁 */ public class WonderReentranrLock { //标记获取锁的线程,原子类型的引用保证原子性 private AtomicReference < Thread > owner = new AtomicReference < > ( ) ; //抢锁失败时进入等待队列 private Queue < Thread > waitQueue = new LinkedBlockingQueue ( ) ; /** * 加锁 */ public void lock ( ) { /

AQS的使用和reentrantlock

心已入冬 提交于 2020-01-31 05:58:10
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(重入锁)功能详解和应用演示

て烟熏妆下的殇ゞ 提交于 2020-01-28 21:19:06
目录 1. ReentrantLock简介 2.ReentrantLock和synchronized的比较 2.1 相同点 2.2不同点 3.ReentrantLock相比synchronized的额外功能 3.1 ReentrantLock可以实现公平锁。 3.2 .ReentrantLock可响应中断 3.3 获取锁时限时等待 4.结合Condition实现等待通知机制 4.1 Condition使用简介 4.2 使用Condition实现简单的阻塞队列 5. 总结 一.ReentrantLock简介 jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock。虽然在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。 接口: Modifier and Type Method Description void lock() 获取锁 void lockInterruptibly() 除非当前线程被中断,否则获取锁定 Condition newCondition() 返回绑定到此Lock实例的新Condition实例 boolean tryLock() 只有在调用时它是空闲的才能获取锁 boolean

ReentrantLock源码分析-JDK1.8

若如初见. 提交于 2020-01-23 20:28:17
浅析JDK1.8 ReentrantLock源码。 写在开篇 ReentrantLock–重入锁,是实现Lock接口的一个同步组件。这篇文章建立在熟悉AQS源码的基础上,同时主要从两个方面来分析ReentrantLock: 重入性的实现原理 公平锁和非公平锁 类的继承关系 ReentrantLock实现了Lock和Serializable接口。 public class ReentrantLock implements Lock, java.io.Serializable { 成员变量 /** ReentrantLock通过sync(AQS的子类)来实现锁 */ private final Sync sync; 这里再说明一下ReentrantLock语境下,AQS的成员变量: /** state用来表示该锁被线程重入的次数。 0表示该锁不被任何线程持有 1表示线程恰好持有该锁1次(未重入) 大于1则表示锁被线程重入state次 */ private volatile int state; /** 标识锁被哪个线程持有 */ private transient Thread exclusiveOwnerThread; 静态内部类 Sync也是一个抽象类,因为锁有非公平和公平的区别。 abstract static class Sync extends

Java多线程

懵懂的女人 提交于 2020-01-20 02:54:47
《Java核心技术》第十版笔记 概念 进程具有自己变量的完备集;线程则共享相同的数据。 抢占式调度:直接中断而不需要实现和 被中断程序 协商 协作式调度:只有在被中断程序同意交出控制权之后才能执行中断 多线程实现 方法一: class MyRunnable implements Runnable { public void run ( ) { . . . } } Runnable r = new MyRunnable ( ) ; Thread t = new Thread ( r ) ; t . start ( ) ; 方法二(不建议): class MyThread extends Thread { public void run ( ) { . . . } } Thread t = new MyThread ( ) ; t . start ( ) ; Thread类 sleep(t):static|线程暂停t毫秒,暂停当前线程的活动,会抛出 InterruptedException void run() void start() static Thread currentThread():返回代表当前执行线程的Thread对象 void interrupt():发送中断请求给一个线程,中断状态为true,如果线程当前被sleep调用阻塞

ReentrantLock源码分析

血红的双手。 提交于 2020-01-19 22:57:30
概述 ReentrantLock是一个可重入的互斥锁,也被称为独占锁。它支持公平锁和非公平锁两种模式。 ReentrantLock的使用方法 下面看一个最初级的例子: public class Test { //默认内部采用非公平实现 ReentrantLock lock=new ReentrantLock(); public void myMethor(){ lock.lock(); //需要加锁的一些操作 //一定要确保unlock能被执行到,尤其是在存在异常的情况下 lock.unlock(); } } 在进入方法后,在需要加锁的一些操作执行之前需要调用lock方法,在jdk文档中对lock方法详细解释如下: 获得锁。 如果锁没有被另一个线程占用并且立即返回,则将锁定计数设置为1。 如果当前线程已经保持锁定,则保持计数增加1,该方法立即返回。 如果锁被另一个线程保持,则当前线程将被禁用以进行线程调度,并且在锁定已被获取之前处于休眠状态,此时锁定保持计数被设置为1。 这里也很好的解释了什么是可重入锁,如果一个线程已经持有了锁,它再次请求获取自己已经拿到的锁,是能够获取成功的,这就是可重入锁。 在需要加锁的代码执行完毕之后,就会调用unlock释放掉锁。在jdk文档之中对,unlock的解释如下: 尝试释放此锁。 如果当前线程是该锁的持有者,则保持计数递减。 如果保持计数现在为零

阻塞队列BlockingQueue之LinkedBlokingQueue

◇◆丶佛笑我妖孽 提交于 2020-01-18 22:11:40
1、简介 LinkedBlokingQueue 是链表实现的有界阻塞队列,此队列的默认和最大长度为 Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。ArrayList和ArrayBlockingQueue一样,内部基于数组来存放元素,而LinkedBlockingQueue则和LinkedList一样,内部基于链表来存放元素。 2、源码分析 2.1、属性 /** * 节点类,用于存储数据 */ static class Node<E> { E item; Node<E> next; Node(E x) { item = x; } } /** 阻塞队列的大小,默认为Integer.MAX_VALUE */ private final int capacity; /** 当前阻塞队列中的元素个数 */ private final AtomicInteger count = new AtomicInteger(); /** * 阻塞队列的头结点 */ transient Node<E> head; /** * 阻塞队列的尾节点 */ private transient Node<E> last; /** 获取并移除元素时使用的锁,如take, poll, etc */ private final ReentrantLock takeLock = new

AbstractQueuedSynchronizer与ReentrantLock

纵然是瞬间 提交于 2020-01-15 13:10:46
介绍 j.u.c包中的 Lock 定义了锁的行为。 而 ReentrantLock 是并发包下提供的一个锁的实现,它是一个可重入的、排他的锁。 ReentrantLock 有的属性也很简单,除了一个 serialVersionUID 外,只有一个 sync 。 ReentrantLock 可以分为公平锁和非公平锁两种。可以在创建时,通过向构造函数传入 fair 参数指定: public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } 无参的构造函数默认会创建一个非公平锁。公平锁和非公平锁的主要区别是:公平锁会保证在锁空闲时,先申请的线程先得到锁;而非公平锁则不考虑线程申请锁的先后顺序,随机让一个线程获得锁。 通过上文的构造函数我们也可以看到,其实内部负责锁的工作的是 Sync 。 ReentrantLock 内部定义了一个抽象类 Sync ,定义了基本锁的行为,然后通过两个具体子类 FairSync 和 NonfairSync 调整具体实现细节,控制公平和非公平的实现(模版模式)。 Sync 类继承自 AbstractQueuedSynchronizer (AQS)。 AQS 是并发包中实现所有锁的基础(无论是共享锁/排他锁,可重入锁/不可重入锁)

ArrayList、LinkedList、Vector、CopyOnWriteArrayList的区别和源码分析

荒凉一梦 提交于 2020-01-15 05:42:19
1. ArrayList ArrayList 是一个数组队列,相当于 动态数组 。与Java中的数组相比,它的 容量能动态增长 。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。 默认容量是10 (从源码中可以看出 每次容量扩大为原来的1.5倍 ,int newCapacity = oldCapacity + (oldCapacity >> 1);)。 ArrayList中的操作不是线程安全的! 所以, 建议在单线程中才使用ArrayList ,而在 多线程中可以选择Vector或者CopyOnWriteArrayList 。 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { ...... /** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10; public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this

ReentrantLock的lock(), tryLock(), lockInterruptibly() 及使用场景示例

試著忘記壹切 提交于 2020-01-14 07:39:23
文章目录 总述 1.ReentrantLock简要介绍 2.ReentrantLock提供的获取锁的方式 2.1 lock() 2.2 tryLock() 2.3 tryLock(long timeout, TimeUnit unit) 2.4 lockInterruptibly() 3.使用场景示例 3.1 对于tryLock()的测试 3.2 tryLock(long,TimeUnit), 3.3 tryLock(long, TimeUnit) + 当线程.interrpt() ==》中断线程 3.4 lockInterruptibly() + 当前线程.interrupt() ==》中断线程 参考博文1 参考博文2 一直在用concurrent包里的东西,最近想研究一下个中细节,先从ReentrantLock提供的集中获取锁的方式开始吧。 总述 lock() 方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。 tryLock() 方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。 tryLock(long time, TimeUnit unit) 方法和tryLock()方法是类似的