reentrantlock

java之AQS和显式锁

China☆狼群 提交于 2020-03-23 09:46:55
  本次内容主要介绍AQS、AQS的设计及使用、 ReentrantLock、 ReentrantReadWriteLock以及手写一个可重入独占锁 1、什么是AQS ?    A QS,队列同步器AbstractQueuedSynchronizer的简写,JDK1.5引入的, 是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。AQS的作者Doug Lea大师期望它能够成为实现大部分同步需求的基础。 2、AQS的设计及其作用    AbstractQueuedSynchronizer是一个抽象类,先看一下其类图。   AQS中里有一个volatile修饰int型的state来代表同步状态,使用同步器提供的3个方法(getState()、setState(int newState)和compareAndSetState(int expect,int update))来改变状态,因为它们能够保证状态的改变是安全的。   AQS使用的是模板方法模式,主要使用方式是继承,且通常将子类推荐定义为静态内部类,子类通过继承AQS并实现它的抽象方法来管理同步状态。AQS自身没有实现任何同步接口,它仅仅是定义了若干同步状态获取和释放的方法来供自定义同步组件使用,同步器既可以支持独占式地获取同步状态

40个Java多线程问题总结

旧城冷巷雨未停 提交于 2020-03-22 20:00:51
40个问题汇总 1、多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓"知其然知其所以然","会用"只是"知其然","为什么用"才是"知其所以然",只有达到"知其然知其所以然"的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法: (1)发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。 单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了 。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。 (2)防止阻塞 从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了

【JUC】JDK1.8源码分析之ReentrantLock(三)

你。 提交于 2020-03-20 03:44:15
一、前言   在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看ArrayBlockingQueue源码会很容易,下面开始正文。 二、ArrayBlockingQueue数据结构   通过源码分析,并且可以对比ArrayList可知,ArrayBlockingQueue的底层数据结构是数组,数据结构如下   说明:ArrayBlockingQueue底层采用数据才存放数据,对数组的访问添加了锁的机制,使其能够支持多线程并发。 三、ArrayBlockingQueue源码分析    3.1 类的继承关系    public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable {}   说明:可以看到ArrayBlockingQueue继承了AbstractQueue抽象类,AbstractQueue定义了对队列的基本操作;同时实现了BlockingQueue接口,BlockingQueue表示阻塞型的队列,其对队列的操作可能会抛出异常;同时也实现了Searializable接口,表示可以被序列化。   

重复请求(并发访问)解决方案

最后都变了- 提交于 2020-03-12 22:41:55
对于查询这些幂等性的请求重复请求其实影响不大,但是对于插入操作的请求,如果有短时间内有重复请求,再加上有事务操作,那么就很有可能造成插入重复数据的问题。对于这种情况首先想到就是数据库添加唯一约束,但是这种方案并不是很推荐而且有很大的局限性。 这块提出一个大致简单的解决方案,对每个用户终端颁发一个唯一标识,在前端请求时带上唯一标识,服务器可以加一个过滤器来处理,每收到一个请求都判断该请求的唯一标识和请求路径是否已经在处理中,如果没有就放入内存中并标识这次请求正在处理,当上次请求还在处理中,又来了一次相同唯一标识和路径的请求,那么第二次(n次)的请求可以直接返回或者等待上次请求完成后一起返回给前端。 import com.mew.kittyapi.util.Objects; import com.mew.kittyapi.util.Strings; import lombok.extern.slf4j.Slf4j; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.HashMap; import java.util.concurrent.locks.ReentrantLock; @Slf4j public

JDK并发包

北城以北 提交于 2020-03-06 10:30:21
1.重入锁(ReentrantLock) 重入锁使用java.util.concurrent.locks.ReentrantLock类来实现,具有与synchronized关键字相似的功能。 1 package com.company; 2 3 import java.util.concurrent.locks.ReentrantLock; 4 5 public class User implements Runnable { 6 private ReentrantLock lock = new ReentrantLock(); 7 static int i = 0; 8 @Override 9 public void run() { 10 lock.lock(); 11 for (int j = 0; j < 10000000; j++) { 12 i++; 13 } 14 System.out.println(i); 15 lock.unlock(); 16 } 17 18 public static void main(String[] args) throws InterruptedException { 19 //注意要使用同一个对象创建线程 20 User u = new User(); 21 Thread t1 = new Thread(u); 22 Thread

Java并发包--ArrayBlockingQueue

寵の児 提交于 2020-03-05 15:21:38
转载请注明出处: http://www.cnblogs.com/skywang12345/p/3498652.html ArrayBlockingQueue介绍 ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列。 线程安全是指,ArrayBlockingQueue内部通过“互斥锁”保护竞争资源,实现了多线程对竞争资源的互斥访问。而有界,则是指ArrayBlockingQueue对应的数组是有界限的。 阻塞队列,是指多线程访问竞争资源时,当竞争资源已被某线程获取时,其它要获取该资源的线程需要阻塞等待;而且,ArrayBlockingQueue是按 FIFO(先进先出)原则对元素进行排序,元素都是从尾部插入到队列,从头部开始返回。 注意:ArrayBlockingQueue不同于ConcurrentLinkedQueue,ArrayBlockingQueue是数组实现的,并且是有界限的;而ConcurrentLinkedQueue是链表实现的,是无界限的。 ArrayBlockingQueue原理和数据结构 ArrayBlockingQueue的数据结构,如下图所示: 说明 : 1. ArrayBlockingQueue继承于AbstractQueue,并且它实现了BlockingQueue接口。 2. ArrayBlockingQueue内部是通过Object

记录面试问题之 ---- 死锁排查

喜欢而已 提交于 2020-03-03 16:37:57
面试常见问题之如何排查死锁 **如何产生死锁 : 1. 共享资源 2. 循环等待 3. 请求保持 4. 不可抢占 ** 考察多线程,在代码中如果使用到多线程,就应该多注意是否会产生死锁:如下例子 ```java import java.util.concurrent.locks.ReentrantLock; public class Code_dead_Thread { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); ReentrantLock lock2 = new ReentrantLock(); Thread thread = new Thread(new Thread_A(lock,lock2)); Thread thread1 = new Thread(new Thread_B(lock,lock2)); thread.start(); thread1.start(); } } class Thread_A implements Runnable{ private ReentrantLock lock ; ReentrantLock lock2 ; Thread_A(ReentrantLock lock,ReentrantLock lock2){ this

重入锁(ReentrantLock)详解

夙愿已清 提交于 2020-02-29 21:40:32
重入锁(ReentrantLock)详解 1、重入锁(ReentrantLock) 支持重进入(表示该锁能够支持一个线程对资源的重复加锁)。 重进入:指任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞 该锁支持获取锁时的公平和非公平性选择(公平锁的效率没非公平性高)ReentrantLock默认采用非公平性。 非公平模式会在一开始就尝试两次获取锁,如果当时正好state的值为0,它就会成功获取到锁,少了排队导致的阻塞/唤醒过程,并且减少了线程频繁的切换带来的性能损耗。 非公平模式有可能会导致一开始排队的线程一直获取不到锁,导致线程饿死 ReentrantLock是通过组合自定义同步器来实现锁的获取和释放。 2、Lock接口源码解析 接口: public interface Lock { /** * Acquires the lock(获取锁). */ void lock(); /** * Acquires the lock unless the current thread is(获取锁,可中断) * @linkplain Thread#interrupt interrupted}. */ void lockInterruptibly() throws InterruptedException; /** * Acquires the lock only if it is

JUC包中的锁框架

天大地大妈咪最大 提交于 2020-02-27 08:52:56
 JUC包中的锁,包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原语,Condition条件,AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三个抽象类,ReentrantLock独占锁,ReentrantReadWriteLock读写锁。由于CountDownLatch,CyclicBarrier和Semaphore也是通过AQS来实现的;因此,我也将它们归纳到锁的框架中进行介绍。   先看看锁的框架图,如下所示。 01. Lock接口   JUC包中的 Lock 接口支持那些语义不同(重入、公平等)的锁规则。所谓语义不同,是指锁可是有"公平机制的锁"、"非公平机制的锁"、"可重入的锁"等等。"公平机制"是指"不同线程获取锁的机制是公平的",而"非公平机制"则是指"不同线程获取锁的机制是非公平的","可重入的锁"是指同一个锁能够被一个线程多次获取。 02. ReadWriteLock   ReadWriteLock 接口以和Lock类似的方式定义了一些读取者可以共享而写入者独占的锁。JUC包只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的

同步锁——ReentrantLock

蓝咒 提交于 2020-02-26 09:33:53
摘自: https://www.cnblogs.com/54chensongxia/p/12360824.html 同步锁——ReentrantLock 本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。 并发编程系列博客传送门 Lock接口简介 # 在JUC包下面有一个 java.util.concurrent.locks 包,这个包提供了一系列基础的锁工具,对传统的synchronizd、wait和notify等同步机制进行补充和增强。下面先来介绍下这个Lock接口。 Lock 接口可以视为 synchronized 的增强版,提供了更灵活的功能。相对于 synchronized , Lock 接口还提供了限时锁等待、锁中断和锁尝试等功能。该接口的定义如下 Copy public interface Lock { // 尝试去获得锁 // 如果锁不可用,当前线程会变得不可用,直到获得锁为止。(中途会忽略中断) void lock(); // 尝试去获取锁,如果锁获取不到,线程将不可用 // 知道获取锁,或者被其他线程中断 // 线程在获取锁操作中,被其他线程中断,则会抛出InterruptedException异常,并且将中断标识清除。 void lockInterruptibly() throws