![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
并发编程
文章平均质量分 59
编程界——周大神
这个作者很懒,什么都没留下…
展开
-
Java并发编程之ReentrantLock 原理
条件变量的实现原理每个条件变量其实就对应着一个等待队列,其实现类是 ConditionObjectawait 流程开始 Thread-0 持有锁,调用 await,进入 ConditionObject 的 addConditionWaiter 流程创建新的 Node 状态为 -2(Node.CONDITION),关联 Thread-0,加入等待队列尾部接下来进入 AQS 的 fullyRelease 流程,释放同步器上的锁unpark AQS 队列中的下一个节点,竞争锁,假设没有其他竞争线程原创 2021-02-28 18:33:19 · 93 阅读 · 0 评论 -
Java并发编程之ReentrantLock 原理
公平锁实现原理源码分析非公平锁是当发现状态为零时,直接去抢这个锁不去检查QAS队列是否有前驱节点,而公平锁要先检查队列中是否有前驱节点,如果没有再执行抢锁,如果有则不抢原创 2021-02-28 16:21:52 · 101 阅读 · 1 评论 -
Java并发编程之ReentrantLock 原理
可打断原理不可打断模式在此模式下,即使它被打断,仍会驻留在 AQS 队列中,一直要等到获得锁后才能得知自己被打断了可打断模式原创 2021-02-28 16:06:21 · 76 阅读 · 0 评论 -
Java并发编程之ReentrantLock 原理
可重入原理源码分析原创 2021-02-28 11:48:05 · 81 阅读 · 0 评论 -
Java并发编程之ReentrantLock 原理
非公平锁原理加锁解锁流程先从构造器开始看,默认为非公平锁实现NonfairSync 继承自 AQS没有竞争时第一个竞争出现时Thread-1 执行了CAS 尝试将 state 由 0 改为 1,结果失败进入 tryAcquire 逻辑,这时 state 已经是1,结果仍然失败接下来进入 addWaiter 逻辑,构造 Node 队列图中黄色三角表示该 Node 的 waitStatus 状态,其中 0 为默认正常状态Node 的创建是懒惰的其中第一个 Node 称为 Du原创 2021-02-28 11:01:51 · 90 阅读 · 0 评论 -
Java并发编程之AQS原理
AQS原理1. 概述全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架特点:用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁getState - 获取 state 状态setState - 设置 state 状态compareAndSetState - cas 机制设置 state 状态独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源提供了基于 FI原创 2021-02-27 12:08:49 · 139 阅读 · 0 评论 -
Java并发编程之线程池(二)
线程池ThreadPoolExecutor1)线程池状态ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量从数字上比较,TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING这些信息存储在一个原子变量 ctl 中,目的是将线程池状态与线程个数合二为一,这样就可以用一次 cas 原子操作进行赋值2) 构造方法corePoolSize 核心线程数目 (最多保留的线程数)原创 2021-02-23 10:56:18 · 147 阅读 · 1 评论 -
Java并发编程之线程池(一)
线程池自定义线程池步骤1:自定义拒绝策略接口步骤2:自定义任务队列步骤3:自定义线程池步骤4:测试原创 2021-02-14 11:14:46 · 87 阅读 · 0 评论 -
Java并发编程之享元模式
享元模式1、简介享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。2. 体现2.1 包装类在JDK中 Boolean,Byte,Short,Integer,Long,Character 等包装类提供了 valueOf 方原创 2021-02-09 23:09:42 · 137 阅读 · 0 评论 -
Java并发编程之不可变
不可变类的使用日期转换的问题问题提出下面的代码在运行时,由于 SimpleDateFormat 不是线程安全的有很大几率出现 java.lang.NumberFormatException 或者出现不正确的日期解析结果,例如:思路 - 不可变如果一个对象在不能够修改其内部状态(属性),那么它就是线程安全的,因为不存在并发修改啊!这样的对象在Java 中有很多,例如在 Java 8 后,提供了一个新的日期格式化类:可以看 DateTimeFormatter 的文档:不可变对象,实际原创 2021-02-09 11:13:24 · 158 阅读 · 0 评论 -
Java并发编程之Unsafe
Unsafe概述Unsafe 对象提供了非常底层的,操作内存、线程的方法,Unsafe 对象不能直接调用,只能通过反射获得Unsafe CAS 操作输出使用自定义的 AtomicData 实现之前线程安全的原子整数 Account 实现Account 实现...原创 2021-02-08 22:23:05 · 89 阅读 · 0 评论 -
Java并发编程之 LongAdder源码
LongAdder源码LongAdder 是并发大师 @author Doug Lea (大哥李)的作品,设计的非常精巧LongAdder 类有几个关键域cas 锁测试输出原理之伪共享得从缓存说起缓存与内存的速度比较因为 CPU 与 内存的速度差异很大,需要靠预读数据至缓存来提升效率。而缓存以缓存行为单位,每个缓存行对应着一块内存,一般是 64 byte(8 个 long)缓存的加入会造成数据副本的产生,即同一份数据会缓存在不同核心的缓存行中CPU 要保证数据的一致性,原创 2021-02-08 15:30:50 · 324 阅读 · 0 评论 -
Java并发编程之JUC
JUC编程原子数组子段更新器原子累加器原子数组AtomicIntegerArrayAtomicLongArrayAtomicReferenceArray有如下方法不安全的数组结果安全的数组结果字段更新器AtomicReferenceFieldUpdater // 域 字段AtomicIntegerFieldUpdaterAtomicLongFieldUpdater利用字段更新器,可以针对对象的某个域(Field)进行原子操作,只能配合 volatile原创 2021-02-08 15:02:46 · 124 阅读 · 0 评论 -
Java并发编程之JUC
JUC编程原子整数J.U.C 并发包提供了:AtomicBooleanAtomicIntegerAtomicLong以 AtomicInteger 为例原子引用为什么需要原子引用类型?AtomicReferenceAtomicMarkableReferenceAtomicStampedReference有如下方法试着提供不同的 DecimalAccount 实现,实现安全的取款操作不安全实现安全实现-使用锁安全实现-使用 CAS测试代码运行结果原创 2021-02-07 10:58:52 · 96 阅读 · 0 评论 -
Java并发编程之共享模型之无锁
无锁并发问题提出原有实现并不是线程安全的执行测试代码某次的执行结果单核的指令交错多核的指令交错解决思路-锁首先想到的是给 Account 对象加锁结果为解决思路-无锁执行测试代码某次的执行结果CAS 与 volatile前面看到的 AtomicInteger 的解决方法,内部并没有用锁来保护共享变量的线程安全。那么它是如何实现的呢?其中的关键是 compareAndSet,它的简称就是 CAS (也有 Compare And Swap 的说法),原创 2021-02-06 16:43:42 · 149 阅读 · 1 评论 -
Java并发编程之volatile关键字原理
volatile关键字原理volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence) 对volatile 变量的写指令后会加入写屏障对 volatile 变量的读指令前会加入读屏障1. 如何保证可见性写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中而读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据2. 如何保证有序性写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之原创 2021-02-02 12:47:16 · 199 阅读 · 0 评论 -
Java并发编程之同步模式
同步模式之顺序控制1. 固定运行顺序比如,必须先 2 后 1 打印1.1 wait notify 版1.2 Park Unpark 版可以看到,实现上很麻烦:首先,需要保证先 wait 再 notify,否则 wait 线程永远得不到唤醒。因此使用了『运行标记』来判断该不该wait第二,如果有些干扰线程错误地 notify 了 wait 线程,条件不满足时还要重新等待,使用了 while 循环来解决此问题最后,唤醒对象上的 wait 线程需要使用 notifyAll,因为『同步对象原创 2021-02-01 14:50:03 · 123 阅读 · 0 评论 -
Java并发编程之ReentrantLock
ReentrantLock相对于 synchronized 它具备如下特点可中断可以设置超时时间可以设置为公平锁支持多个条件变量与 synchronized 一样,都支持可重入基本语法可重入可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住输出可打断示例输出注意如果是不可中断模式,那么即使使用了 interrupt 也不会让等待中断输出锁超时立刻失败原创 2021-01-31 22:41:27 · 150 阅读 · 0 评论 -
Java并发编程之活跃性
活跃性死锁有这样的情况:一个线程需要同时获取多把锁,这时就容易发生死锁t1 线程 获得 A对象 锁,接下来想获取 B对象 的锁 t2 线程 获得 B对象 锁,接下来想获取 A对象 的锁 例:结果定位死锁检测死锁可以使用 jconsole工具,或者使用 jps 定位进程 id,再用 jstack 定位死锁:避免死锁要注意加锁顺序另外如果由于某个线程进入了死循环,导致其它线程一直等待,对于这种情况 linux 下可以通过 top 先定位到CPU 占用高的 Java 进程,再利用原创 2021-01-31 11:32:23 · 152 阅读 · 0 评论 -
Java并发编程之线程状态转换
线程状态转换(从Java角度解释)假设有线程 Thread t情况 1 NEW --> RUNNABLE当调用 t.start() 方法时,由 NEW --> RUNNABLE情况 2 RUNNABLE <–> WAITINGt 线程用 synchronized(obj) 获取了对象锁后调用 obj.wait() 方法时,t 线程从 RUNNABLE --> WAITING调用 obj.notify() , obj.notifyAll() , t.inte原创 2021-01-31 10:50:45 · 170 阅读 · 0 评论 -
Java并发编程之 Park & Unpark
Park & Unpark基本使用它们是 LockSupport 类中的方法先 park 再 unpark输出先 unpark 再 park输出特点与 Object 的 wait & notify 相比wait,notify 和 notifyAll 必须配合 Object Monitor 一起使用,而 park,unpark 不必park & unpark 是以线程为单位来【阻塞】和【唤醒】线程,而 notify 只能随机唤醒一个等待线程,notify原创 2021-01-27 17:02:44 · 1375 阅读 · 1 评论 -
Java并发编程之设计模式
异步编程之生产者消费者1. 定义要点与前面的保护性暂停中的 GuardObject 不同,不需要产生结果和消费结果的线程一一对应消息队列可以用来平衡生产和消费的线程资源生产者仅负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据JDK 中各种阻塞队列,采用的就是这种模式2. 实现应用某次运行结果...原创 2021-01-27 16:42:01 · 98 阅读 · 0 评论 -
Java并发编程之设计模式
同步模式之保护性暂停1. 定义即 Guarded Suspension,用在一个线程等待另一个线程的执行结果要点有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)JDK 中,join 的实现、Future 的实现,采用的就是此模式因为要等待另一方的结果,因此归类到同步模式2. 实现应用一个线程等待另一个线程的执行结果执行结果3. 带超时版 GuardedObj原创 2021-01-27 14:17:23 · 126 阅读 · 0 评论 -
Java并发编程之共享模型
wait notify小故事 - 为什么需要 wait由于条件不满足,小南不能继续进行计算但小南如果一直占用着锁,其它人就得一直阻塞,效率太低于是老王单开了一间休息室(调用 wait 方法),让小南到休息室(WaitSet)等着去了,但这时锁释放开,其它人可以由老王随机安排进屋直到小M将烟送来,大叫一声 [ 你的烟到了 ] (调用 notify 方法)小南于是可以离开休息室,重新进入竞争锁的队列API 介绍obj.wait() 让进入 object 监视器的线程到 wa原创 2021-01-27 10:32:39 · 123 阅读 · 0 评论 -
Java并发编程之synchronized详解
synchronized详解1. 轻量级锁轻量级锁的使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。轻量级锁对使用者是透明的,即语法仍然是 synchronized假设有两个方法同步块,利用同一个对象加锁创建锁记录(Lock Record)对象,每个线程都的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的Mark Word让锁记录中 Object reference 指向锁对象,并尝试用 cas 替换 Object 的原创 2021-01-24 11:46:02 · 127 阅读 · 0 评论 -
Java并发编程之Monitor
MonitorMonitor概念Java对象头以 32 位虚拟机为例普通对象数组对象其中 Mark Word 结构为64 位虚拟机 Mark WordMonitor 原理Monitor 被翻译为监视器或管程每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针Monitor 结构如下刚开始 Monitor 中 Owner 为 null原创 2021-01-24 10:16:12 · 245 阅读 · 0 评论 -
Java并发编程之共享模型
变量的线程安全分析成员变量和静态变量是否线程安全?如果它们没有共享,则线程安全如果它们被共享了,根据它们的状态是否能够改变,又分两种情况如果只有读操作,则线程安全如果有读写操作,则这段代码是临界区,需要考虑线程安全局部变量是否线程安全?局部变量是线程安全的但局部变量引用的对象则未必如果该对象没有逃离方法的作用访问,它是线程安全的如果该对象逃离方法的作用范围,需要考虑线程安全局部变量线程安全分析每个线程调用 test1() 方法时局部变量 i,会在每个线程的栈帧内原创 2021-01-20 14:52:22 · 74 阅读 · 0 评论 -
Java并发编程之共享模型
线程八锁所谓的“线程八锁”其实就是考察 synchronized 锁住的是哪个对象情况1:12 或 21情况2:1s后12,或 2 1s后 1情况3:3 1s 12 或 23 1s 1 或 32 1s 1情况4:2 1s 后 1情况5:2 1s 后 1情况6:1s 后12, 或 2 1s后 1情况7:2 1s 后 1情况8:1s 后12, 或 2 1s后 1...原创 2021-01-20 13:59:40 · 71 阅读 · 0 评论 -
Java并发编程之两阶段终止模式
两阶段终止模式在一个线程 T1 中如何“优雅”终止线程 T2?这里的【优雅】指的是给 T2 一个料理后事的机会。1. 错误思路使用线程对象的 stop() 方法停止线程stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀 死后就再也没有机会释放锁,其它线程将永远无法获取锁使用 System.exit(int) 方法停止线程目的仅是停止一个线程,但这种做法会让整个程序都停止2. 两阶段终止模式2.1利用 isInterruptedinterrupt 可以原创 2021-01-19 11:45:15 · 302 阅读 · 0 评论 -
Java并发编程之Java线程
Java线程线程 API线程状态join 方法详解为什么需要 join下面的代码执行,打印 r 是什么?分析因为主线程和线程 t1 是并行执行的,t1 线程需要 1 秒之后才能算出 r=10而主线程一开始就要打印 r 的结果,所以只能打印出 r=0解决方法用 sleep 行不行?为什么?用 join,加在 t1.start() 之后即可应用之同步(案例1)以调用方角度来讲,如果需要等待结果返回,才能继续运行就是同步不需要等待结果返回,就能继续运行就是异步等原创 2021-01-19 10:54:45 · 87 阅读 · 0 评论 -
Java并发编程之Java线程
Java线程1.创建和运行线程2.查看线程3.线程 API创建和运行线程方法一,直接使用 Thread例如:输出方法二,使用 Runnable 配合 Thread把【线程】和【任务】(要执行的代码)分开1)Thread 代表线程2)Runnable 可运行的任务(线程要执行的代码)例如:输出Java 8 以后可以使用 lambda 精简代码原理之 Thread 与 Runnable 的关系分析 Thread 的源码,理清它与 Runnable 的关系小结1)原创 2021-01-18 11:41:22 · 97 阅读 · 0 评论 -
java并发编程之线程与进程
进程与线程1.进程和线程的概念2.并行和并发的概念3.线程基本应用进程和线程进程1)程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的2)当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。3)进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器等),也有的程序只能启动一个实例进程(例如网易云音乐、3原创 2021-01-17 12:12:44 · 76 阅读 · 0 评论