reentrantlock

14个Java并发容器,你用过几个?

假如想象 提交于 2019-11-28 16:04:58
作者: acupt 前言 不考虑多线程并发的情况下,容器类一般使用ArrayList、HashMap等线程不安全的类,效率更高。在并发场景下,常会用到ConcurrentHashMap、ArrayBlockingQueue等线程安全的容器类,虽然牺牲了一些效率,但却得到了安全。 上面提到的线程安全容器都在java.util.concurrent包下,这个包下并发容器不少,今天全部翻出来鼓捣一下。 仅做简单介绍,后续再分别深入探索。 并发容器介绍 ConcurrentHashMap:并发版HashMap CopyOnWriteArrayList:并发版ArrayList CopyOnWriteArraySet:并发Set ConcurrentLinkedQueue:并发队列(基于链表) ConcurrentLinkedDeque:并发队列(基于双向链表) ConcurrentSkipListMap:基于跳表的并发Map ConcurrentSkipListSet:基于跳表的并发Set ArrayBlockingQueue:阻塞队列(基于数组) LinkedBlockingQueue:阻塞队列(基于链表) LinkedBlockingDeque:阻塞队列(基于双向链表) PriorityBlockingQueue:线程安全的优先队列 SynchronousQueue:读写成对的队列

Java容器源码(三)——CopyOnWriteArrayList源码分析(基于JDK8)

强颜欢笑 提交于 2019-11-28 11:04:08
文章目录 (一)、概述 (二)、适用场景 (二)、类名 (三)、成员变量 (四)、构造方法 (五)、set方法 (六)、add方法 (七)、remove方法 (八)、addIfAbsent方法 更多Java容器源码分析可以参考: Java容器源码分析系列(持续更新中!) (一)、概述 CopyOnWriteArrayList的特点主要是实现了读写分离,读操作时不加锁,写操作才进行加锁,防止并发时写入导致数据丢失 在进行写操作的时候,不是在原数组上直接修改,而是创建一个新的数组,对原数组进行复制修改等操作后,再将指针指向新的数组。 (二)、适用场景 CopyOnWriteArrayList主要使用于读多写少的应用场景,这会大大提高读的性能 缺点: List item会占用较多内存,因为在写操作的时候,都需要创建一个新的数 可能会出现数据不一致的情况,读操作可能读到过时的数据,因为写操作不在原数组上进行,可能还未来得及指向新数组。 (二)、类名 public class CopyOnWriteArrayList < E > implements List < E > , RandomAccess , Cloneable , java . io . Serializable { CopyOnWriteArrayList实现了List接口、RandomAccess接口

JUC AQS ReentrantLock源码分析

一曲冷凌霜 提交于 2019-11-28 10:12:40
  为了了解java并发包下的 ReentrantLock 可重入锁 和 AbstractQueuedSynchronizer 抽象队列同步器,我自己创建了这两个类,改一下类名,把他们的代码贴过来,再删除英文注释,一步步的分析,再贴上自己的中文理解。然后我发现 BacAQS只有940行,BacReentrantLock 只有230行,然后攻克她。Bac 是我起的英文名,高大上的寓意是 大数据BigData ,Ai人工智能,CloudComputing云计算。读音:巴西。不是喜欢足球,是自己胖得像球。。。  直接上代码,后续会慢慢解读,补充中文注释。你也可以按这个方法,一起学习哦。可重入锁: package www.itbac.com; import java.util.Collection; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; //可重入锁 public class BacReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID =

How to implement a reentrant locking mechanism in objective-c through GCD?

和自甴很熟 提交于 2019-11-28 08:43:43
I have an objective-c class with some methods, which use a GCD queue to ensure that concurrent accesses to a resource take place serially (standard way to do this). Some of these methods need to call other methods of the same class. So the locking mechanism needs to be re-entrant. Is there a standard way to do this? At first, I had each of these methods use dispatch_sync(my_queue, ^{ // Critical section }); to synchronize accesses. As you know, when one of these methods calls another such method, a deadlock happens because the dispatch_sync call stops the current executing until that other

多线程与高并发(六) Lock

只愿长相守 提交于 2019-11-28 07:13:59
之前学习了如何使用synchronized关键字来实现同步访问,Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。 不同于synchronized是Java语言的关键字,是内置特性,Lock不是Java语言内置的,Lock是一个类,通过这个类可以实现同步访问。而且synchronized同步块执行完成或者遇到异常是锁会自动释放,而lock必须调用unlock()方法释放锁,因此在finally块中释放锁。 一、 Lock 接口 先看看lock接口定义了哪些方法: void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition();

并发编程--并发编程框架概述

拟墨画扇 提交于 2019-11-28 01:44:06
JDK给我们提供了一个并发编程的包java.util.current,并发编程包中是锁功能更加强大,并且他允许更灵活的使用锁。 JUC包中的锁,包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原语,Condition条件,AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三个抽象类,ReentrantLock独占锁,ReentrantReadWriteLock读写锁。由于CountDownLatch,CyclicBarrier和Semaphore也是通过AQS来实现的;因此,我也将它们归纳到锁的框架中进行介绍。 先看看锁的框架图,如下所示。 1、Lock接口 JUC包中的 Lock 接口支持那些语义不同(重入、公平等)的锁规则。所谓语义不同,是指锁可是有"公平机制的锁"、"非公平机制的锁"、"可重入的锁"等等。"公平机制"是指"不同线程获取锁的机制是公平的",而"非公平机制"则是指"不同线程获取锁的机制是非公平的","可重入的锁"是指同一个锁能够被一个线程多次获取。 2、ReadWriteLock读写锁接口 ReadWriteLock 接口以和Lock类似的方式定义了一些读取者可以共享而写入者独占的锁。JUC包只有一个类实现了该接口

J.U.C并发包(1)

北慕城南 提交于 2019-11-28 01:17:12
J.U.C并发包(1) AbstractQueuedSynchronizer AbstractQueuedSynchronizer是JUC并发包中锁的底层支持,AbstractQueuedSynchronizer是抽象同步队列,简称AQS,是实现同步器的基础组件,并发包中锁的实现底层就是使用AQS实现, 从类图的关系可以看到AQS是一个FIFO的双向队列,内部通过节点head 和 tail 记录队首和队尾元素,队列元素类型为Node。其中Node中Thread变量用来存放进入AQS队列里面的线程 Node 节点内部SHARED用来标记该线程是获取共享资源时候被阻塞挂起来后放入AQS队列, EXCLUSIVE标记线程是获取独占资源时候被挂起后放入AQS队列; waitStatus记录当前线程等待状态,分别为CANCELLED(线程被取消了),SIGNAL(线程需要被唤醒),CONDITION(线程在条件队列里面等待),PROPAGATE(释放共享资源时候需要通知其他节点); AQS中维持了一个单一的状态信息state,可以通过getState,setState,compareAndSetState 函数修改其值;对于ReentrantLock 的实现来说,state 可以用来表示当前线程获取锁的可重入次数; pre记录当前节点的前驱节点,next记录当前节点后继节点

ReentrantLock

巧了我就是萌 提交于 2019-11-28 00:53:42
Condition可以选择性的进行线程通知,在调度线程上更加灵活。 wait/notify方法进行通知时,被通知的线程是有JVM随机选择的,Condition的signal可以"选择性的通知" 生产者/消费者模式 打印奇数偶数 //锁对象 ,必须是同一把锁public class Num { int i=1; boolean flag=false; Lock lock=new ReentrantLock(); Condition condition=lock.newCondition(); } public class EvenPrint implements Runnable { private Num num; public EvenPrint(Num num){ this.num=num; } @Override public void run() { while (num.i<=500){ //上锁 num.lock.lock(); if(num.i%2==0){ System.out.println(Thread.currentThread().getName()+ "偶数——————"+num.i); num.i++; //唤醒 奇数线程 num.condition.signal(); }else{ try {          //等待 num.condition

JUC 总结

别说谁变了你拦得住时间么 提交于 2019-11-27 18:25:18
1创建线程的方式 比较常见的一个问题了,一般就是四种: (1)继承Thread类 (2)实现Runnable接口 (3)实现 Callable 接口:该方式相较于实现 Runnable 接口,方法多了返回值,并且可以抛出异常 FutureTask (4)线程池 2 start()方法和run()方法的区别 只有调用了start()方法,才会表现出多线程的特性,不同线程的run()方法里面的代码交替执行。如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码 全部执行完毕之后,另外一个线程才可以执行其run()方法里面的代码。 3什么是线程安全 如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么你的代码就是 线程安全的 。 (1)不可变 像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用 设置不可变对象的原因: 因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误.此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读取数据时不会有任何问题.我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象. (2)绝对线程安全 不管运行时环境如何

Actual use of lockInterruptibly for a ReentrantLock

若如初见. 提交于 2019-11-27 16:15:49
问题 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? 回答1: 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