reentrantlock

Java同步的三种实现方式

匿名 (未验证) 提交于 2019-12-02 21:45:52
1.使用synchronized关键字修饰类或者代码块; 2.使用Volatile关键字修饰变量; 3.在类中加入重入锁 举例子:多个线程在处理一个 共享变量 的时候,就会出现线程安全问题。(相当于多个窗口卖票的操作) 非同步状态下: public static void main(String[] args){ Increase increase = new Increase(); int count = 10; while (count != 0){ new Thread(() -> { increase.increasementAndPrint(); }).start(); count --; } } static class Increase { private int i = 0; void increasementAndPrint() { System.out.print(i++ + "\n"); } } 这种情况下可能会导致多个线程输出的i相同: 0 0 1 2 3 4 5 6 7 8 使用同步: 1.使用synchronized关键字 //保证原子性和有序性 static class Increase { private int i = 0; synchronized void increasementAndPrint() { System.out.println

ReadWriteLock: 读写锁

跟風遠走 提交于 2019-12-02 21:36:25
ReadWriteLock: 读写锁 ReadWriteLock: JDK1.5提供的读写分离锁,采用读写锁分离可以有效帮助减少锁竞争。 特点: 1).使用读写锁。当线程只进行读操作时,可以允许多个线程同时读 2).写写操作,读写操作间依然需要相互等待和持有锁。 一).使用读写锁与使用重入锁进行读读写操作 开启200个线程,测试读写锁和重入锁的读效率。 使用重入锁进行读写操作: ReentrantLock_Rw import java.util.concurrent.locks.ReentrantLock; /** * 使用重入锁进行读写操作 * 线程的读写使用同一把锁。 */ public class ReentrantLock_RW { private static ReentrantLock lock = new ReentrantLock(); private static int value ; //读操作 public Object handleRead() throws InterruptedException { try { //获取锁 lock.lock(); //模拟读操作,读操作耗时越多,读写锁的优势越明显 Thread.sleep(1); return value; }finally { lock.unlock(); } } /** * 写操作 */

通过一个生活中的案例场景,揭开并发包底层AQS的神秘面纱

烈酒焚心 提交于 2019-12-02 19:31:26
本文导读 生活中案例场景介绍 联想到 AQS 到底是什么 AQS 的设计初衷 揭秘 AQS 底层实现 最后的总结 当你在学习某一个技能的时候,是否曾有过这样的感觉,就是同一个技能点学完了之后,过了一段时间,如果你没有任何总结,或者是不经常回顾,遗忘的速度是非常之快的。 忘记了之后,然后再重新学,因为已经间隔了一段时间,再次学习又当做了新的知识点来学。这种状态如此反复,浪费了相同的时间,但学习效果却收效甚微。 每当遇到这种情况,我们可以停下来,思考一下。对于某一个技术知识点理解起来不是那么好懂的时候,或者是学习起来有点吃力的时候,咱们可以尝试找找生活中的例子来联想下。 因为技术源于生活。 找到一个合适的生活案例,然后结合你自己做笔记总结和动手实践的过程。定期的去回顾一下,慢慢的就会理解的更加透彻。 1、生活中案例场景介绍 今天我们就举一个生活中的例子来理解下并发底层的AQS。 大家如果去过某些大医院的话,就能知道,由于互联网的快速发展,医院的挂号、交费、取药的流程都是比较方便的,交费也可以使用支付宝、微信支付了,而不用带现金了。 医生开完单子,交费完成 ,单子上都会有一个长条二维码,可以直接在取药的地方自助扫码,叫号系统自动分配取药窗口,然后你在关注下指定窗口等待着叫号就可以了,叫到你的时候再过去取药,而不需要一直在等待着。 我们用一张图来直观的感受下: 这里面涉及到了几个角色: 1

关于公平锁和非公平锁的理解

妖精的绣舞 提交于 2019-12-02 18:40:13
这是看完你就明白的锁系列的第四篇文章 文章一览请看这里 看完你就应该能明白的悲观锁和乐观锁 看完你就明白的锁系列之自旋锁 看完你就明白的锁系列之锁的状态 此篇文章我们来探讨一下什么是锁的公平性 锁的公平性与非公平性 我们知道,在并发环境中,多个线程需要对同一资源进行访问,同一时刻只能有一个线程能够获取到锁并进行资源访问,那么剩下的这些线程怎么办呢?这就好比食堂排队打饭的模型,最先到达食堂的人拥有最先买饭的权利,那么剩下的人就需要在第一个人后面排队,这是理想的情况,即每个人都能够买上饭。那么现实情况是,在你排队的过程中,就有个别不老实的人想走捷径,插队打饭,如果插队的这个人后面没有人制止他这种行为,他就能够顺利买上饭,如果有人制止,他就也得去队伍后面排队。 对于正常排队的人来说,没有人插队,每个人都在等待排队打饭的机会,那么这种方式对每个人来说都是公平的,先来后到嘛。这种锁也叫做公平锁。 那么假如插队的这个人成功买上饭并且在买饭的过程不管有没有人制止他,他的这种行为对正常排队的人来说都是不公平的,这在锁的世界中也叫做非公平锁。 那么我们根据上面的描述可以得出下面的结论 公平锁 表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。而 非公平锁 就是一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁

ReentrantLock doesn't work out

送分小仙女□ 提交于 2019-12-02 10:33:18
I can't figure out why the code doesn't work properly. The problem is that ReentrantLock doesn't lock methods invocation in ThreadClass.run() Resource-class which methods are assumed to be locked in ThreadClass public class ResourceClass { private int i; public void setIncrement() { i++; } public int getIncrement() { return i; } } Thread-class public class ThreadClass implements Runnable { private ResourceClass resource; private ReentrantLock reentrantLock = new ReentrantLock(); ThreadClass(ResourceClass r) { resource = r; } public void run() { reentrantLock.lock(); try { resource.setIncrement

深入理解ReentrantLock

江枫思渺然 提交于 2019-12-02 08:31:31
在Java中通常实现锁有两种方式,一种是synchronized关键字,另一种是Lock。二者其实并没有什么必然联系,但是各有各的特点,在使用中可以进行取舍的使用。首先我们先对比下两者。 实现: 首先最大的不同:synchronized是基于JVM层面实现的,而Lock是基于JDK层面实现的。曾经反复的找过synchronized的实现,可惜最终无果。但Lock却是基于JDK实现的,我们可以通过阅读JDK的源码来理解Lock的实现。 使用: 对于使用者的直观体验上Lock是比较复杂的,需要lock和realse,如果忘记释放锁就会产生死锁的问题,所以,通常需要在finally中进行锁的释放。但是synchronized的使用十分简单,只需要对自己的方法或者关注的同步对象或类使用synchronized关键字即可。但是对于锁的粒度控制比较粗,同时对于实现一些锁的状态的转移比较困难。例如: 特点: tips synchronized Lock 锁获取超时 不支持 支持 获取锁响应中断 不支持 支持 优化: 在JDK1.5之后synchronized引入了偏向锁,轻量级锁和重量级锁,从而大大的提高了synchronized的性能,同时对于synchronized的优化也在继续进行。期待有一天能更简单的使用java的锁。 在以前不了解Lock的时候,感觉Lock使用实在是太复杂

锁的分类

╄→尐↘猪︶ㄣ 提交于 2019-12-02 02:24:26
对竞争的态度: 乐观锁(java.util.concurrent包中的原子类)与悲观锁(Synchronized) 等待锁的人是否公平而言: 公平锁(new ReentrantLock(true))与非公平锁(new ReentrantLock()) 是否可以共享: 共享锁和独享锁;ReadWriteLock,其读锁是共享锁,其写锁是独享锁 来源: https://www.cnblogs.com/-qilin/p/11725755.html

java多线程并发面试题

我怕爱的太早我们不能终老 提交于 2019-12-01 15:29:18
1、多线程有什么用? (1)发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。 (2)防止阻塞 从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。 (3)便于建模 这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务,任务B、任务C、任务D

# XX 课堂之ReentrantLock源码学习总结 (一)

南楼画角 提交于 2019-12-01 12:17:07
[^ ]: 以下源码分析基于JDK1.8 ReentrantLock 示例 private ReentrantLock lock = new ReentrantLock(true); public void f(){ try { lock.lock(); //do something } finally { lock.unlock(); } } 源码解析(公平锁-lock流程) 构造方法 //默认是非公平锁 public ReentrantLock() { sync = new NonfairSync(); } //构造参数传入是否使用公平锁 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } [^]: 下文主要以公平锁为示例做分析 核心变量 private final Sync sync; //大名鼎鼎的 AQS abstract static class Sync extends AbstractQueuedSynchronizer{...} //队列(链表)头 private transient volatile Node head; //队列(链表)尾 private transient volatile Node tail; //状态 state

Java高并发处理总结

邮差的信 提交于 2019-12-01 11:08:50
自己参考大牛博客及视频写了一些关于并发的感悟,高并发的处理思路,无外乎以下几种 1 代码层面: 锁优化措施(见本文内容)、尽量简化事务和减少事务 2 应用层面:缓存 队列 限流 熔断 3数据库层面: 分库分表 读写分离 JDK常见并发包处理工具中,ReentrantLock、countdownlanth、currenthasp、AQS源码一定要多读多看,理解里面的设计精髓。带着问题去思考,去看源码,会更加有效。 一:ReentrantLock源码分析: 阻塞队列是利用ReentrantLock配合condition中的asigl、await方法实现的 读写分离锁:读锁是利用到了共享模式,写锁是用到了独占模式,与synchronize相比,可以避免读读互排斥,降低了锁的范围 1.Java并发库中ReetrantReadWriteLock实现了ReadWriteLock接口并添加了可重入的特性 2.ReetrantReadWriteLock读写锁的效率明显高于synchronized关键字 3.ReetrantReadWriteLock读写锁的实现中,读锁使用共享模式;写锁使用独占模式,换句话说,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的 4.ReetrantReadWriteLock读写锁的实现中,需要注意的,当有读锁时,写锁就不能获得;而当有写锁时