reentrantlock

第四章-java多线程核心技术-Lock锁-第一篇

若如初见. 提交于 2019-11-27 16:10:45
lock锁的使用 ReentrantLock锁的使用 在JDK5.0版本之前,重入锁的性能远远好于synchronized关键字,JDK6.0版本之后synchronized 得到了大量的优化,二者性能也不分伯仲,但是重入锁是可以完全替代synchronized关键字的。除此之外,重入锁又自带一系列其他功能:可中断响应、锁申请等待限时、公平锁。另外可以结合Condition来使用,使其更是逼格满满。 请看如下使用代码 public class ReenTrantLock { private Lock lock = new ReentrantLock(); public void testLock() { lock.lock(); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "---" + i); } lock.unlock(); } } /** * @program: demo * @description: demo * @author: lee * @create: 2018-09-03 **/ public class ThreadA extends Thread { private ReenTrantLock reenTrantLock ;

JUC锁框架——重入锁ReentrantLock

北城以北 提交于 2019-11-27 16:10:06
重入锁(ReentrantLock)   ReentrantLock是一种可重入的互斥锁,并且加锁是一种显式操作,对逻辑控制的灵活性远远大于synchronized关键字。重入锁是可以完全替代synchronized。并且重入锁的性能是远高于synchronized的,但是jdk6.0开始,jdk对synchronized做了大量的优化,使得两者性能差距不大。另外,ReentrantLock可结合Condition、以及提供了中断响应、锁申请等待限时、公平锁等。 公平锁、非公平锁(ReentrantLock)   ReentrantLock分为“公平锁”和“非公平锁”。它们的区别体现在获取锁的机制上是否公平。在“公平锁”的机制下,线程依次排队获取锁;而“非公平锁”在锁是可获取状态时,不管自己是不是在队列的开头都会获取锁。  运行如下代码,对比公平锁和非公平锁的运行结果 public static void main(String[] args) throws InterruptedException { Lock noFairReentrantLock = new ReentrantLock(); Lock fairReentrantLock = new ReentrantLock(true); Thread[] threads = new Thread[10]; for(int

java中的各种锁详细介绍

杀马特。学长 韩版系。学妹 提交于 2019-11-27 13:35:32
转自: https://blog.csdn.net/axiaoboge/article/details/84335452 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。 Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录: 1. 乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有此概念对应的实际应用。 先说概念。对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。 而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。 乐观锁在Java中是通过使用无锁编程来实现

源码解析关于java阻塞容器:ArrayBlockingQueue,LinkedBlockingQueue等

六月ゝ 毕业季﹏ 提交于 2019-11-27 12:15:24
Java的阻塞容器介绍JDK18 一ArrayBlockingQueue 类的定义 重要的成员变量 初始化 一些重要的非公开的方法 入队和出队操作重要 入队操作add offer put 出队操作poll peek take remove 其他方法 内部类迭代器 类的定义 重要的成员 初始化 重要的方法 内部类 Itrs 类的定义 二LinkedBlockingQueue 类的定义 重要的成员变量 初始化 一些重要的非公开的方法 入队和出队操作重要 入队操作offer put 出队操作poll peek take remove 其他方法 内部类迭代器Itr 类的定义 重要的成员 初始化 重要的方法 Java的阻塞容器介绍(JDK1.8) 先来看看阻塞容器和其他容器之间的层级关系 Collection AbstractCollection Queue BlockingQueue AbstractQueue ArrayBlockingQueue LinkedBlockingQueue SynchronousQueue PriorityBlockingQueue 我们就挑这四个重要的实现类来讲解。 一、ArrayBlockingQueue 1.类的定义 public class ArrayBlockingQueue < E > extends AbstractQueue < E >

Java8 - ArrayBlockingQueue源码

删除回忆录丶 提交于 2019-11-27 12:11:23
一、概述 ArrayBlockingQueue 是一个基于循环数组的有界阻塞队列,一旦创建了队列,那么其容量就不能再改变了,它不允许 null 值的插入。它是通过使用 ReentrantLock 来保证线程安全。 ArrayBlockingQueue 支持对生产者线程和消费者线程进行公平的调度,默认情况下是不保证公平性的。公平性通常会降低吞吐量,但是可以减少了可变性和避免了线程饥饿。 二、循环数组 PS:接触过循环数组这种数据结构的,可以直接跳过这一小节。 通常,队列的实现方式有数组和链表两种方式。对于数组这种实现方式来说,我们可以通过维护一个队尾指针,使得在入队的时候可以在O(1)的时间内完成;但是对于出队操作,在删除队头元素之后,必须将数组中的所有元素都往前移动一个位置,这个操作的复杂度达到了O(n),效果并不是很好。如下图所示: 为了解决这个问题,我们可以使用另外一种逻辑结构来处理数组中各个位置之间的关系。假设现在我们有一个数组A[1…n],我们可以把它想象成一个环型结构,即A[n]之后是A[1],如下图所示:那么我们便可以使用两个指针,分别维护队头和队尾两个位置,使入队和出队操作都可以在O(1)的时间内完成,如下图所示。当然,这个环形结构只是逻辑上的结构,实际的物理结构还是一个普通的数据。 到此,我们对 ArrayBlockingQueue 使用的数据结构有了一定的了解

Java 多线程加锁

萝らか妹 提交于 2019-11-27 09:26:16
以前的同步操作 基本上都是用到 synchronized 关键字,类似代码如下: synchronized(obj){ //dosomething... }来做到同步, 在 JDK5.0 里面有这么一个对象,ReentrantLock,发觉她的加锁编程的方式非常的适合日常的加锁习惯, EG: package com.thread.synchronise; import java.util.concurrent.locks.ReentrantLock; public class SynchroTest extends Thread{ private int count = 0; private final ReentrantLock lock = new ReentrantLock(); public void run() { //这里加了几次锁,在后面就的要相应的解锁 几次 lock.lock(); // block until condition holds try { count++; System.out.println(" count = "+count); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("

并发容器学习—CopyOnWriteArrayList与CopyOnWriteArraySet

a 夏天 提交于 2019-11-27 04:12:41
一、CopyOnWriteArrayList并发容器 1.CopyOnWriteArrayList的底层数据结构 CopyOnWriteArrayList的底层实现是数组,CopyOnWriteArrayList是ArrayList的一个线程安全的变体,其增删改操作都是通过对底层数组的重新复制来实现的。这种容器内存开销很大,但是在读操作频繁(查询),写操作(增删改)极少的场合却极用,并且每一次写操作都是在一块新的空间上进行的,不存在并发问题。 2.CopyOnWriteArrayList的继承关系 CopyOnWriteArrayList继承关系如下图所示,List接口和Collection接口在学习ArrayList时已经分析过,不在多说。 3.重要属性和构造方法 public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { //可重入锁 final transient ReentrantLock lock = new ReentrantLock(); //底层实现,用于存放数据的数组 private transient volatile Object[] array; //获取数组 final Object[] getArray()

java并发编程之美-阅读记录7

孤街浪徒 提交于 2019-11-27 03:49:14
java并发包中的并发队列 7.1ConcurrentLinkedQueue   线程安全的无界非阻塞队列(非阻塞队列使用CAS非阻塞算法实现),其底层数组使用单向列表实现,对于出队和入队操作使用CAS非阻塞来实现线程安全的。   1、结构:      ConcurrentLinkedQueue内部的对列使用的是单向链表实现,并且有两个用volatile修改的节点头结点head和tail尾节点    private transient volatile Node<E> head; private transient volatile Node<E> tail; // 默认的无常构造使头节点和尾节点都指向一个值为null的哨兵节点 public ConcurrentLinkedQueue() { head = tail = new Node<E>(null); } // 同时还提供了一个有参构造,将指定集合中的数据插入到链表中 public ConcurrentLinkedQueue(Collection<? extends E> c) { Node<E> h = null, t = null; for (E e : c) { checkNotNull(e); Node<E> newNode = new Node<E>(e); if (h == null) h = t =

JUC锁框架——基于AQS的实现,从ReentrantLock认识独占和共享

馋奶兔 提交于 2019-11-27 02:35:00
JDK中有以下基于AQS的实现 ReentrantLock CountDownLatch Semaphore ReentrantReadWriteLock CyclicBarrier (委托给ReentrantLock) 首先关于源码中经常出现 final ReentrantLock takeLock = this.takeLock 写法: 这是一个有关volatile变量的lock-free的典型习惯编码。在第一行第一次到读到变量后,另一个线程会更新这个值,但你只对初始读到的值感兴趣。 另外,即使我们讨论的成员变量不是 volatile而是final, 这个习惯用法也与CPU缓存有关:从栈读变量比从堆读变量会更cache-friendly,本地变量最终绑定到CPU寄存器的可能性更高。 ReentrantLock的独占和共享: 基本上一致,区别: 非公平锁是: 先state+1,然后直接得到锁, 而公平锁则是: 先尝试去获取锁,如果得到了锁则state+1. 实现公平性的关键在于:如果锁被占用且当前线程不是持有者也不是等待队列的第一个,则进入等待队列。 可见是否公平实际上是对处于等待队列中的线程来说的。 ReentrantLock都是把具体实现委托给内部类 而不是直接继承自AbstractQueuedSynchronizer, 这样的好处是用户不会看到不需要的方法,

Java并发指南11:解读 Java 阻塞队列 BlockingQueue

我们两清 提交于 2019-11-26 23:32:44
解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程池问题,我相信很多人都一知半解的,包括我自己在仔仔细细看源码之前,也有许多的不解,甚至有些地方我一直都没有理解到位。 说到线程池实现,那么就不得不涉及到各种 BlockingQueue 的实现,那么我想就 BlockingQueue 的问题和大家分享分享我了解的一些知识。 本文没有像之前分析 AQS 那样一行一行源码分析了,不过还是把其中最重要和最难理解的代码说了一遍,所以不免篇幅略长。本文涉及到比较多的 Doug Lea 对 BlockingQueue 的设计思想,希望有心的读者真的可以有一些收获,我觉得自己还是写了一些干货的。 本文直接参考 Doug Lea 写的 Java doc 和注释,这也是我们在学习 java 并发包时最好的材料了。希望大家能有所思、有所悟,学习 Doug Lea 的代码风格,并将其优雅、严谨的作风应用到我们写的每一行代码中。 目录 阻塞队列概览 Java中的阻塞队列 BlockingQueue源码分析 BlockingQueue 实现之 ArrayBlockingQueue BlockingQueue 实现之 LinkedBlockingQueue