reentrantlock

Java并发系列(10)彻底理解ReentrantLock

好久不见. 提交于 2019-11-29 08:32:38
本站小福利 点我获取阿里云优惠券 原文作者:github:CL0610/Java-concurrency 免责声明: 1.本文所转载文章均来自公开网络。 2.如果出处标注有误或侵犯到原著作者权益,请联系删除。 3.转载文章请注明原文链接和作者,否则产生的任何版权纠纷均与本站无关。 1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁, 支持重入性,表示能够对共享资源能够重复加锁, 即当前线程获取该锁再次获取不会被阻塞 。在java关键字synchronized隐式支持重入性 (关于synchronized可以 看这篇文章 ), synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持 公平锁和非公平锁 两种方式。那么, 要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平锁和非公平锁。 2. 重入性的实现原理 要想支持重入性,就要解决两个问题:**1. 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功;2. 由于锁会被获取n次,那么只有锁在被释放同样的n次之后, 该锁才算是完全释放成功。**通过 这篇文章 ,我们知道

锁的内存语义

白昼怎懂夜的黑 提交于 2019-11-29 05:38:11
锁的内存语义 锁的释放-获取建立的happens-before关系 锁是Java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送信息. 假设线程A执行writer()方法,随后线程B执行reader()方法.根据happens-before规则,这个过程happens-before关系可以分为3类. 根据程序次序规则,1 happens-before 2,2 happens-before 3;4 happens-before 5,5 happensbefore 6。 根据监视器锁规则,3 happens-before 4 根据happens-before的传递性,2 happens-before 5 上述happens-before关系的图形化表示形式如下图所示 每一个箭头链接的两个节点,代表了一个happens-before关系。黑色箭头表示程序顺序规则;橙色箭头表示监视器锁规则;蓝色箭头表示组合这些规则后提供的happens-before保证。 上图中在线程A释放了锁之后,随后线程B获取同一个锁。在上图职工2 happens-before 5,因此,线程A在释放锁之前所有可见的共享变量,在线程B获取同一个锁之后,将立刻变得对线程B可见。 锁的释放和获取的内存语义 当线程释放锁时

LinkedBlockingQueue

前提是你 提交于 2019-11-29 04:21:32
转: https://www.jianshu.com/p/fb79f074be28 数组的长度在创建时就必须确定,如果数组长度小了,那么ArrayBlockingQueue队列很容易就被阻塞,如果数组长度大了,就容易浪费内存。 而队列这个数据结构天然适合用链表这个形式,而LinkedBlockingQueue就是使用链表方式实现的阻塞队列。 一. 链表实现 1.1 Node内部类 /** * 链表的节点,同时也是通过它来实现一个单向链表 */ static class Node<E> { E item; // 指向链表的下一个节点 Node<E> next; Node(E x) { item = x; } } 有一个变量e储存数据,有一个变量next指向下一个节点的引用。它可以实现最简单地单向列表。 1.2 怎样实现链表 /** * 它的next指向队列头,这个节点不存储数据 */ transient Node<E> head; /** * 队列尾节点 */ private transient Node<E> last; 要实现链表,必须有两个变量,一个表示链表头head,一个表示链表尾last。head和last都会在LinkedBlockingQueue对象创建的时候被初始化。 last = head = new Node<E>(null); 注意这里用了一个小技巧

从ReentrantLock实例分析AbstractQueuedSynchronizer和ConditionObject

。_饼干妹妹 提交于 2019-11-29 03:21:46
1.实例:3个线程交替打印1,2,3一定次数 代码如下: import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class TestReentrantLock { private static final int times = 12; private static int count = 0; public static void main(String[] args) { // 实现1,2,3交替打印times次 Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); Thread print1 = new Thread(() -> { lock.lock(); for (int i = 0; i < times; i++) { try { while (count % 3 != 0)

[******] java多线程连续打印abc

大城市里の小女人 提交于 2019-11-29 02:38:35
题目描述 建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。 5种方法 使用synchronized, wait和notifyAll 使用Lock->ReentrantLock 和 state标志 使用Lock->ReentrantLock 和Condition(await 、signal、signalAll) 使用Semaphore 使用AtomicInteger 扩展:采用join实现(一次性打印) 5.1 使用synchronized, wait和notifyAll public class ABC7 { private static Object o = new Object();//所对象 private static int state = 0;//控制顺序 private static int PRINT_NUMBER = 10;//打印次数 private static int THREAD_NUM = 3;//线程数量 static class ThreadGenetic implements Runnable { char name; int data; public ThreadGenetic(char name, int data){

Actual use of lockInterruptibly for a ReentrantLock

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-29 01:52:29
What do you actually use for this method lockInterruptibly ? I have read the API however it's not very clear to me. Could anybody express it in other words? The logic is the same as for all interruptible blocking methods: it allows the thread to immediately react to the interrupt signal sent to it from another thread. How this particular feature is used is up to the application design. For example, it can be used to kill a contingent of threads in a pool which are all waiting to aquire a lock. lockInterruptibly() may block if the the lock is already held by another thread and will wait until

Java多线程三(线程安全的集合及java.util.concurrent包的锁)

依然范特西╮ 提交于 2019-11-28 22:57:01
一、线程安全的集合 JDK1.5之前,可以使用Venctor和Hashtable,也可以由java.util.Collections来创建线程安全的集合,如:Connections.synchronizedSet(Set<T>); Connections.synchronizedList(List<T>);Connections.synchronizedMap(Map<K, V>)等,其简单的原理是每个方法都增加了synchronized来保证线程安全。 JDK1.5之后,提供了java.util.concurrent并发包,它提供的新集合类允许通过在语义中的少量更改来获得更高的并发。 CopyOnWriteArrayList 其中的set、add、remove等方法,都使用了ReentrantLock的lock()来加锁,unlock()来解锁。当增加元素的时候使用Arrays.copyOf()来拷贝副本,在副本上增加元素,然后改变原引用指向副本。 CopyOnWriteArraySet 使用了CopyOnWriteArrayList来存储数据,remove方法调用CopyOnWriteArrayList的remove方法。add方法调用了CopyOnWriteArrayList的addIfAbsent方法,addIfAbsent同样使用了ReentrantLock的lock(

并发编程-AQS

左心房为你撑大大i 提交于 2019-11-28 21:47:11
概念 AQS是AbstactQueuedSynchronizer的简称,它是一个Java提供的底层同步工具类,用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态。AQS的主要作用是为Java中的并发同步组件提供统一的底层支持,例如ReentrantLock,CountdowLatch就是基于AQS实现的,用法是通过继承AQS实现其模版方法,然后将子类作为同步组件的内部类。 同步队列 一个双端队列,遵循FIFO原则,主要作用是用来存放在锁上阻塞的线程,当一个线程尝试获取锁时,如果已经被占用,那么当前线程就会被构造成一个Node节点加到同步队列的尾部,队列的头节点是成功获取锁的节点,当头节点线程释放锁时,会唤醒后面的节点并释放当前头节点的引用。 独占锁的获取和释放流程 ######获取 1. 调用入口方法acquire(arg) 2. 调用模版方法tryAcquire(arg)尝试获取锁,若成功则返回,若失败则走下一步 3. 将当前线程构造成一个Node节点,并利用CAS将其加入到同步队列到尾部,然后该节点对应的线程进入自旋状态。 自旋时,首先判断其前驱节点是否为头节点&是否成功获取同步状态,两个条件都成立,则将当前线程的节点设置为头节点,如果不是,则利用LockSupport.park(this)将当前线程挂起 ,等待被前驱节点唤醒 ######释放 1

线程死锁

元气小坏坏 提交于 2019-11-28 19:53:06
原创转载请注明出处: https://www.cnblogs.com/agilestyle/p/11424647.html 死锁:一组互相竞争资源的线程因互相等待,导致“永久”阻塞的现象。 解决死锁,要么重启,要么规避 那如何避免死锁呢?要避免死锁就需要分析死锁发生的条件,只有以下这四个条件都发生时才会出现死锁: 互斥,共享资源 X 和 Y 只能被一个线程占用; 占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X; 不可抢占,其他线程不能强行抢占线程 T1 占有的资源; 循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。 反过来分析,也就是说只要破坏其中一个,就可以成功避免死锁的发生。 模拟一个死锁的程序 1 package org.fool.test; 2 3 import java.util.concurrent.TimeUnit; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 public class DeadLockTest { 8 private static Lock lockA = new ReentrantLock(); 9

java.util.concurrent.locks包中的ReentrantLock之非公平策略解析

让人想犯罪 __ 提交于 2019-11-28 18:59:49
简介: ReentrantLock作为一个可重入互斥锁,具有与Synchronized隐式监视器相同的功能,除此之外,还有更强的扩展性。 如果一个线程调用lock(),如果该锁未被另外一个线程持有,则成功获取锁并返回;如果当前线程已经持有该锁,则直接返回。可以通过 isHeldByCurrentThread () 和 getHoldCount ()查看该线程是否已持有该锁以及次数。 Public ReentrantLock(boolean fairness):此构造器,可以通过设置fairness=true来保证ReentrantLock的公平性策略:等待时间最长的线程优先获得锁。采用公平策略比采用默认策略(非公平策略)的lock,在程序吞吐量方面前者远远低于后者;在尝试获取锁的次数与避免饥饿性方面却有着较小的差异。原文描述:( Programs using fair locks accessed by many threads may display lower overall throughput (i.e., are slower; often much slower) than those using the default setting, but have smaller variances in times to obtain locks and guarantee