reentrantlock

ReentrantLock

﹥>﹥吖頭↗ 提交于 2019-12-09 10:55:54
  在jdk5.0之前AQS框架下的锁的性能是远远超过synchronized的,从jdk6.0开始对synchronized做出优化后二者在性能上差异已经不大了。ReentrantLock的有点在于: 灵活性。加锁解锁的过程是可控的,synchronized加锁解锁过程是编译完成后JVM来实现的 可响应中断。synchronized下无法获得锁的线程是BLOCKED的,不可以相应中断。AQS下所有的锁包括重入锁无法获得锁是WAITING的,可相应中断,可以用来解决死锁问题 超时获得锁。同样可以用来缓解死锁问题 支持公平锁避免饥饿 好基友Condition。虽然synchronized下同样有Object的wait notify方法,但Condition队列更灵活、更可控。 使用CAS来实现原子操作 使用LockSupport中的park unpark实现阻塞原语 1.1 基本使用   一个老生常谈的多线程自增的例子。由于i++的非原子性,在不采取任何措施的情况下最终的结果是小于等于200000的,为了使最终的结果为200000需要采取措施保障i++不可分割,在i++前后加锁即可。   虽然用synchronized可实现同样的结果,但用重入锁可以自己来加锁解锁,况且还省了一个大括号不是? public class myThread implements Runnable {

重入锁----ReentrantLock

。_饼干妹妹 提交于 2019-12-09 10:54:57
本节主要从下述四个方面介绍重入锁。 1.什么是重入锁? 2.为什么要引用重入锁? 3.重入锁是怎么实现的? 4.分析java并发包中ReentrantLock。 什么是重入锁 重入锁,支持重进入的锁,表示该锁能够支持一个线程对它重复加锁,即线程在获得锁之后再次获取该锁时不会被阻塞。 为什么要引用重入锁? 以子类重写父类方法为例: Mutix是不支持重入的锁。(代码摘抄自《java并发编程的艺术》) 1 import java.util.concurrent.TimeUnit; 2 import java.util.concurrent.locks.*; 3 4 5 6 public class Mutix implements Lock 7 { 8 private static class Sync extends AbstractQueuedSynchronizer{ 9 //是否处于占用状态 10 protected boolean isHeldExclusively(){ 11 return this.getState()==1; 12 } 13 protected boolean tryAcquire(int acquires){ 14 if(compareAndSetState(0,1)){ 15 setExclusiveOwnerThread(Thread

AQS系列(一)- ReentrantLock的加锁

落爺英雄遲暮 提交于 2019-12-07 22:58:27
前言 AQS即AbstractQueuedSynchronizer,是JUC包中的一个核心抽象类,JUC包中的绝大多数功能都是直接或间接通过它来实现的。本文是AQS系列的第一篇,后面会持续更新多篇,争取将JUC包中AQS相关的常用功能讲清楚,一方面巩固自己的知识体系,一方面亦可与各位园友互相学习。寒冷的冬天,要用技术来温暖自己。 一、AQS与ReentrantLock的关系 先奉上一张自制的丑陋类图 从下往上看,ReentrantLock类内部有两个静态内部类FairSync和NonfairSync,分别代表了公平锁和非公平锁(注意ReentrantLock实现的锁是可重入排它锁)。这两个静态内部类又共同继承了ReentrantLock的一个内部静态抽象类Sync,此抽象类继承AQS。 类的关系搞清楚了,我们下面一起看一下源码。 二、源码解读 ReentrantLock的默认构造方法创建的是非公平锁,也可以通过传入true来指定生成公平锁。 下面我们以公平锁的加锁过程为例,进行解读源码 。在解读源码之前需要先明确一下AQS中的state属性,它是int类型, state=0表示当前lock没有被占用,state=1表示被占用 ,如果是重入状态,则重入了几次state就是几。 1 public class JucLockDemo1 { 2 public static void

java线程调度:Lock ReentrantLock Condition

戏子无情 提交于 2019-12-07 11:30:53
一、我们要打印1到9这9个数字,由A线程先打印1,2,3,然后由B线程打印4,5,6,然后再由A线程打印7,8,9. 这道题有很多种解法,现在我们使用Condition来做这道题(使用Object的wait,notify方法的解法在 这里 )。 原文: http://outofmemory.cn/java/java.util.concurrent/lock-reentrantlock-condition 这是一个不错的网站: http://outofmemory.cn/java/ 二、解决AsyncTask能暂停,能取消的问题,重用性很高: https://mobiarch.wordpress.com/2012/07/20/pausing-and-resuming-background-work-in-android/ 三、ReentrantLock可重入锁的使用场景: http://my.oschina.net/noahxiao/blog/101558 来源: oschina 链接: https://my.oschina.net/u/1389206/blog/489731

Markdown使用

微笑、不失礼 提交于 2019-12-06 15:01:54
[TOC] ## 为二级标题 ### 为三级标题 #### 为四级标题 **加粗** *强调* `private static Lock lock = new ReentrantLock();` ![](https://www.baidu.com/img/baidu_jgylogo3.gif) [百度](http://www.baidu.com) > 我的建议是,如果真的还有1个月要去面试了,那你最起码用几天的时间,网上搜三五十个最常见、最典型的算法题,反复练习、务必熟练。 1. 有序列表 2. 有序列表 - java - GIS - JS 分页符 * * * 分节符 - - - 分段符 _ _ _ ```java private static Lock lock = new ReentrantLock(); private static Condition condition = lock.newCondition(); ``` ~~删除线~~ - [ ] 论文 - [ ] 工作 - [x] 吃 ++下划线++ [^注脚] [^]: 注脚引用 | Java Core | 高级 | |--------|--------| | 变量、控制 | jvm、并发 | ==高亮了吗== @[](嵌入对象) <!--注释--> 来源: https://www.cnblogs.com

java.concurrent.ReentrantLock - why we want to acquire the same lock multiple times [duplicate]

廉价感情. 提交于 2019-12-06 03:23:32
问题 This question already has answers here : Why use a ReentrantLock if one can use synchronized(this)? (7 answers) Closed 6 years ago . I know if using ReentrantLock, it allows the same thread to acquire the same lock more than once. Internally, it has a counter to count the number of the lock acquisition. If you acquired the same lock twice, you would need to release it twice. But my question is that why would someone want to acquire the lock multiple times, should one time acquisition be

【细谈Java并发】谈谈LinkedBlockingQueue(转)

删除回忆录丶 提交于 2019-12-05 16:47:36
最近在看concurrent包的知识,看到 LinkedBlockingQueue ,发现一篇好文推荐给大家。 原文地址: 【细谈Java并发】谈谈LinkedBlockingQueue 1、简介 上篇我们介绍了ArrayBlockingQueue的相关方法的原理,这一篇我们来学习一下 ArrayBlockingQueue 的“亲戚” LinkedBlockingQueue 。在集合框架里,想必大家都用过ArrayList和LinkedList,也经常在面试中问到他们之间的区别。ArrayList和ArrayBlockingQueue一样,内部基于数组来存放元素,而LinkedBlockingQueue则和LinkedList一样,内部基于链表来存放元素。 LinkedBlockingQueue实现了BlockingQueue接口,这里放一张类的继承关系图(图片来自之前的文章: 说说队列Queue ) LinkedBlockingQueue不同于ArrayBlockingQueue,它如果不指定容量,默认为 Integer.MAX_VALUE ,也就是无界队列。所以为了避免队列过大造成机器负载或者内存爆满的情况出现,我们在使用的时候建议手动传一个队列的大小。 2、源码分析 2.1、属性 /** * 节点类,用于存储数据 */ static class Node<E> { E

java多线程,多线程加锁以及Condition类的使用

邮差的信 提交于 2019-12-05 15:10:27
看了网上非常多的运行代码,很多都是重复的再说一件事,可能对于java老鸟来说,理解java的多线程是非常容易的事情,但是对于我这样的菜鸟来说,这个实在有点难,可能是我太菜了,网上重复的陈述对于我理解这个问题一点帮助都没有.所以这里我写下我对于这个问题的理解,目的是为了防止我忘记. 还是从代码实例开始讲起: import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Predicate; public class Main { public static void main(String[] args) throws InterruptedException { MyBlockingQueue<Integer> queue = new MyBlockingQueue<>(1); for (int i = 0; i < 10; i++) { int data = i; new Thread(() -> { try { queue.enqueue(data);

一篇文章,彻底理解ReentrantLock

女生的网名这么多〃 提交于 2019-12-05 14:36:38
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。在java关键字synchronized隐式支持重入性,synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平锁和非公平锁。 2. 重入性的实现原理 要想支持重入性,就要解决两个问题:**1. 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功;2. 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功,我们知道,同步组件主要是通过重写AQS的几个protected方法来表达自己的同步语义。针对第一个问题

ReentrantLock加锁解锁过程

与世无争的帅哥 提交于 2019-12-05 08:50:53
公平锁 调用lock方法加锁 进入acquire方法获取加锁的许可 进入tryacquire 首先获取当前线程和status状态,status默认为0 假如现在t1线程进入,然后t2线程进入(t2进入时t1还没有释放锁) if c==0成立,然后判断是否需要排队,调用hasqueuedpredecessors方法 此时的头和尾都是null,此方法返回false,所以上面if(!hasqueuedpredecessors())成立,然后进行cas操作,将status改为1 然后设置持有锁的是当前线程。最后返回true。即t1拿到锁继续执行自己的业务逻辑。。。。 1、如果t2执行lock方法的时候t1已经释放锁,也就不会存在竞争,一次执行。 2、如果t1还没有释放锁,t2也会走上面的代码。 走到tryacquire方法尝试去获取锁的时候肯定失败,因为t1还在占用。方法返回false。 然后会执行addwriter方法进入队列排队。 首先创建一个节点node,节点里包含属性thread,pre,next,是一个双向链表 由于tail=null,所以会走enq方法。 此处无限循环,t==null也成立,首先会先初始化一个新的Node,node里的信息目前为空。然后设置为头部。(其实队列里的头部永远都是一个空节点,空节点的意思是有node对象,只不过里面的thread属性为空) 继续循环