reentrantlock

JDK源码那些事儿之LinkedBlockingQueue

佐手、 提交于 2019-11-26 20:01:36
今天继续讲解阻塞队列,涉及到了常用线程池的其中一个队列LinkedBlockingQueue,从类命名部分我们就可以看出其用意,队列中很多方法名是通用的,只是每个队列内部实现不同,毕竟实现的都是同一个接口BlockingQueue,可以自行查看接口源码,下面我们一起看下LinkedBlockingQueue实现的源码部分 前言 JDK版本号:1.8.0_171 LinkedBlockingQueue是链表实现的线程安全的无界的阻塞队列 内部是通过Node节点组成的链表来实现的 线程安全说明的是内部通过两个ReentrantLock锁保护竞争资源,实现了多线程对竞争资源的互斥访问,这里入队和出队互不影响 无界,默认链表长度为Integer.MAX_VALUE,本质上还是有界 阻塞队列,是指多线程访问竞争资源时,当竞争资源已被某线程获取时,其它要获取该资源的线程需要阻塞等待 队列通过Node对象组成的链表实现,与ArrayBlockingQueue不同的地方在于,ArrayBlockingQueue是有界的,初始化需指定长度,LinkedBlockingQueue不定义长度时,默认Integer.MAX_VALUE,相当于“无界”了,但是这样会造成一些问题,这部分后边说,同时保证并发和阻塞部分使用了2个互斥锁分别对入队和出队互斥操作,这样来看,独立开来提升了队列的吞吐量

从源码角度彻底理解ReentrantLock(重入锁)

懵懂的女人 提交于 2019-11-26 19:33:54
目录 1.前言 2.AbstractQueuedSynchronizer介绍 2.1 AQS是构建同步组件的基础 2.2 AQS的内部结构(ReentrantLock的语境下) 3 非公平模式加锁流程 3.1加锁流程真正意义上的入口 3.2 尝试获取锁的通用方法:tryAcquire() 3.3 获取锁失败的线程如何安全的加入同步队列:addWaiter() 3.4 线程加入同步队列后会做什么:acquireQueued() 3.5 加锁流程源码总结 4.非公平模式解锁流程 4.1 解锁流程源码解读 4.2 解锁流程源码总结 5. 公平锁相比非公平锁的不同 6. 一些疑问的解答 6.1 为什么基于FIFO的同步队列可以实现非公平锁? 6.2 为什么非公平锁性能好 7. 阅读源码的收获 1.前言 在 ReentrantLock(重入锁)功能详解和应用演示 这篇文章里我们讲解并演示了ReentrantLock(重入锁)的各种功能,其中就谈到ReentrantLock可以有公平锁和非公平锁的不同实现,只要在构造它的时候传入不同的布尔值,继续跟进下源码我们就能发现,关键在于实例化内部变量 sync 的方式不同,如下所示 /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. *

10.彻底理解ReentrantLock

不打扰是莪最后的温柔 提交于 2019-11-26 19:33:44
1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁, 支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞 。在java关键字synchronized隐式支持重入性(关于synchronized可以 看这篇文章 ),synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持 公平锁和非公平锁 两种方式。那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平锁和非公平锁。 2. 重入性的实现原理 要想支持重入性,就要解决两个问题: 1. 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功;2. 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功。 通过 这篇文章 ,我们知道,同步组件主要是通过重写AQS的几个protected方法来表达自己的同步语义。针对第一个问题,我们来看看ReentrantLock是怎样实现的,以非公平锁为例,判断当前线程能否获得锁为例,核心方法为nonfairTryAcquire: final boolean nonfairTryAcquire(int

彻底理解ReentrantLock

六眼飞鱼酱① 提交于 2019-11-26 19:33:27
1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。在java关键字synchronized隐式支持重入性(关于synchronized可以看这篇文章),synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平锁和非公平锁。 2. 重入性的实现原理 要想支持重入性,就要解决两个问题:1. 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功;2. 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功。通过这篇文章,我们知道,同步组件主要是通过重写AQS的几个protected方法来表达自己的同步语义。针对第一个问题,我们来看看ReentrantLock是怎样实现的,以非公平锁为例,判断当前线程能否获得锁为例,核心方法为nonfairTryAcquire: - final boolean nonfairTryAcquire(int acquires) {

彻底理解ReentrantLock

心已入冬 提交于 2019-11-26 19:33:16
5.ReentrantLock的介绍 ReenTrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞.在java关键字synchronized隐式支持重入性(关于synchro.那么nized可以看这篇文章),synchronized通过获取自增,释放自减的方式实现重入.与此同时,ReentrantLock还支持公平锁和非公平锁两种方式.那么,想要完全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习: 重入性的实现原理 公平锁和非公平锁 5.1重入性的实现原理 想要支持重锁入性,就是解决两个问题: 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功 由于锁会被获取n次,那么只有锁在被释放同样n次之后,该锁才算完全释放成功. **通过 这篇文章 ,我们知道,同步组件主要是通过重写AQS的几个protected方法来表达自己的同步语义。针对第一个问题,我们来看看ReentrantLock是怎样实现的,以非公平锁为例,判断当前线程能否获得锁为例,核心方法为nonfairTryAcquire: final boolean nonfairTryAcquire(int acquires) { final Thread

Android 多线程之几个基本问题

我只是一个虾纸丫 提交于 2019-11-26 18:08:54
Android中的进程和线程 Android中的一个应用程序一般就对应着一个进程,多进程的情况可以参考 Android 多进程通信之几个基本问题 Android中更常见的是多线程的情况,一个应用程序中一般都有包括UI线程等多个线程。Android中规定网络访问必须在子线程中进行,而操作更新UI则只能在UI线程。 常见的网络请求库,如OkHttp、Volly等都为我们封装好了线程池,所以我们在进行网络请求时一般不是很能直观地感受到创建线程以及切换线程的过程。 线程是一种很宝贵的资源,要避免频繁创建销毁线程,一般推荐用线程池来管理线程。 线程的状态 线程可能存在6种不同的状态:新创建(New)、可运行(Runnable)、阻塞状态(Blocked)、等待状态(Waiting)、限期等待(Timed Waiting)、终止状态(Terminated) 新创建(New):创建后但还未启动的线程(还没有调用start方法)处于这种状态 可运行(Runnable):一旦调用了start方法,线程就处于这种状态。需要注意的是此时线程可能正在执行,也可能在等待CPU分配执行的时间 阻塞状态(Blocked):表示线程被锁阻塞,等待获取到一个排他锁。在程序等待进入同步区域时,线程将进入这种状态 等待状态(Waiting):处于这种状态的线程不会被分配CPU执行时间,它们要等待被其他线程显示地唤醒

JAVA多线程系列--Lock锁-ReentrantLock之Condition应用

人盡茶涼 提交于 2019-11-26 17:18:34
1. Condition synchronized与wait()和nitofy()/notifyAll()方法相结合可以实现等待/通知模型,ReentrantLock同样可以,但是需要借助Condition,且Condition有更好的灵活性,具体体现在: 1、一个Lock里面可以创建多个Condition实例,实现多路通知 2、notify()方法进行通知时,被通知的线程时Java虚拟机随机选择的,但是ReentrantLock结合Condition可以实现有选择性地通知,这是非常重要的 3、在使用 实现等待/通知模型的时候 ,await()和signal()之前,必须要先lock()获得锁,使用完毕在finally中unlock()释放锁,这和wait()/notify()/notifyAll()使用前必须先获得对象锁是一样的: 2. 例一: /** * ReentrantLock * @author niyuelin * */ public class ReeterLockCondition implements Runnable{ public static ReentrantLock lock = new ReentrantLock() ; public static Condition condition = lock .newCondition() ;

多线程4-Lock的使用

无人久伴 提交于 2019-11-26 17:17:38
之前学习了通过synchronized关键字实现线程同步效果。除此之外,通过Lock对象来实现同步效果。 知识点 1- ReentrantLock类的使用 2- ReentrantReadWriteLock类的使用 ReentrantLock类 案例说明ReentrantLock可实现线程同步效果。 运行类: package ReentrantLock_part1; public class Test { public static void main(String[] args) { Service1 service1 = new Service1(); Thread1 thread1 = new Thread1(service1); Thread1 thread2 = new Thread1(service1); Thread1 thread3 = new Thread1(service1); thread1.start(); thread2.start(); thread3.start(); } } 线程类: package ReentrantLock_part1; public class Thread1 extends Thread{ private Service1 service1; public Thread1(Service1 service1) { super(

Java多线程编程-(7)-使用ReentrantReadWriteLock实现Lock并发

做~自己de王妃 提交于 2019-11-26 17:13:06
前几篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁代码谈一下volatile关键字 Java多线程编程-(4)-线程本地ThreadLocal的介绍与使用 Java多线程编程-(5)-线程间通信机制的介绍与使用 Java多线程编程-(6)-你还在使用wait/notify实现进程间的通信吗? 上一篇介绍了使用 ReentrantLock实现同步互斥。 ReentrantLock具有完全互斥排他的效果,即同一时间只能有一个线程在执行ReentrantLock.lock()之后的任务。 类似于我们集合中有 同步类容器 和 并发类容器 ,HashMap也是完全排他的,即使是读也只能同步执行,而ConcurrentHashMap就可以实现同一时刻多个线程之间并发。为了提高效率,ReentrantLock的升级版 ReentrantReadWriteLock 就可以实现效率的提升。 ReentrantReadWriteLock有两个锁: 一个是与读相关的锁,称为“ 共享锁 ”;另一个是与写相关的锁,称为“ 排它锁 ” 。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。 在没有线程进行写操作时

Java5 多线程实践

自作多情 提交于 2019-11-26 16:51:16
2006 年 1 月 18 日 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来实现该服务器。 回页首 初始化