多线程笔记
本专栏源自《Java 并发编程实战》阅读笔记和感悟
HuangGang_clown
这个作者很懒,什么都没留下…
展开
-
Balking 模式
Balking 模式Balking 与 Guarded Suspension模式类似,本质上是一种规范化解决“多线程版本if”的方案。两者之间的不同在于,Balking模式在条件变量不满足时,直接退出;而Guarded Suspension模式会等待到条件变量满足时,继续往下执行。Balking模式典型应用场景,使用synchronized单次初始化class InitTest{ boolean inited = false; synchronized void init() {原创 2021-12-29 22:34:32 · 371 阅读 · 0 评论 -
Thread-Per-Message 与 Worker Thread 模式
Thread-Per-Message 与 Worker Thread 模式并发编程领域的问题总结为三个核心问题:分工、同步和互斥。Thread-Per-Message模式旨在解决“分工”的问题,该模式为每个任务分配一个独立的线程。在java中,为每个任务创建、销毁线程的成本很高,所以Thread-Per-Message 模式在java世界并不流行。进而出现了Worker Thread 模式,Worker Thread 模式好比车间里的工人,有活儿了,大家一起干,没活了就聊聊天等着,车间里的工人数量往原创 2021-12-29 22:33:38 · 219 阅读 · 0 评论 -
多线程中的设计模式
多线程中的设计模式Immutability 模式共享变量不可变,便是线程安全的,同时也是高效率的,无状态的服务也是安全的,不会成为分布式系统的性能瓶颈类的属性用final修饰提供只读的方式访问属性类通过final修饰????:当属性为对象时,应考虑不变性的边界,即作为类属性的对象,拥有的属性是否可变上述三个条件保证了类的不可变性Immutability模式的应用享元模式,可以理解为一个对象池的模型,对象存在时,直接获取,对象不存在时,先创建,放入池中,再使用;目的是减小内原创 2021-12-29 22:33:00 · 133 阅读 · 0 评论 -
Guarded Suspension模式
Guarded Suspension 模式考虑一个场景,当两个服务通过MQ进行交互时,服务A生产消息,服务B消费消息,两者为异步操作,我们如何来保证A消费到B返回的结果呢?Guarded Suspension模式所谓 Guarded Suspension,直译过来就是“保护性地暂停”。Guarded Suspension模式的结构图如下,其中包含:一个受保护的对象GuardedObject两个成员方法:get(Predicate p) 和 onChanged(T obj)方法Guard原创 2021-10-08 11:42:29 · 501 阅读 · 0 评论 -
Synchronized 实现原理
synchronized锁定某个对象,才能访问某段代码public class SynchronizedTest { static Object lock = new Object(); static List<Integer> list = new ArrayList<>(10); public static void main(String[] args) { synchronized (lock) { li原创 2021-09-09 23:06:16 · 179 阅读 · 0 评论 -
Fork/Join 2021-09-01
Fork/Joinjdk除了提供ThreadPoolExecutor这样的线程池,还提供了ForkJoinPool,顾名思义,先fork,再join,先分解任务,处理各个子任务,再合并,采用“分治”的思想分治,分而治之。把一个复杂的问题分解成多个相似的子问题,然后再把子问题分解成更小的子问题,直到子问题简单到可以直接求解像归并排序,快速排序,二分查找都属于分支算法,以及大数据领域计算框架MapReduce同样利用了分支思想分治任务模型任务的分解ⅰ将任务分解到可以直接计算结果的粒度结原创 2021-09-01 15:58:37 · 118 阅读 · 0 评论 -
StampedLock 2021-07-27
StampedLockStampedLock是比ReadWriteLock效率更高的读写锁StampedLock支持写锁,悲观读锁和乐观读悲观读锁StampedLock lock = new StampedLock();long rStamp = lock.readLock(); try { ... } finally { lock.unlockRead(rStamp);}写锁long wStamp = lock.writeLock()原创 2021-07-27 13:11:31 · 66 阅读 · 0 评论 -
ReadWriteLock 2021-07-27
ReadWriteLockJava除了提供管程和信号量两种同步原语,还提供了ReadWriteLock,StampedLock等,目的是分场景优化性能,提升易用性。读多写少是并发场景中非常普遍的,我们通常使用缓存来解决此类问题。缓存之所以能提升性能,重要的条件就是缓存数据一定是读多写少。Java SDK中为我们提供了读写锁ReadWriteLock,使用方便,性能也很好。读写锁的特性允许多个线程同事读取共享变量只允许一个线程写共享变量若一个写线程正在执行写操作,此时禁止读线程读共享变量原创 2021-07-27 00:42:44 · 72 阅读 · 0 评论 -
Semaphore 2021-07-27
Semaphore信号量,用于实现资源限流的工具类,允许多个线程同时访问同一临界区信号量模型,一个计数器,一个等待队列,三个方法三个方法,init(),设置计数器的初始值down(), 计数器值减一,计数器值<0,线程阻塞,加入等待队列up(), 计数器值加一,计数器值<=0,唤醒等待队列中的一个线程,从队列中移除上述三个方法都是原子性的,是由信号量模型的实现方来保证的。java中通过Semaphore实现信号量,借助**acquire()和release()**来控原创 2021-07-27 00:12:51 · 68 阅读 · 0 评论 -
Lock和Condition 2021-07-22
Lock与ConditionLock为什么java有了语言层面的synchronized,还在SDK中提供了Lock这种互斥锁呢?synchronzied 有可能会 产生死锁,而Lock 是可以中断的锁,可以破坏死锁中“占用且不可抢占的条件”。Lock支持响应中断、支持超时,并且支持非阻塞地获取锁,完美解决了“不可抢占”的问题。Lock提供的API,//支持中断lockInterruptibly() throws InterruptedException //支持超原创 2021-07-22 23:59:10 · 99 阅读 · 0 评论 -
安全性问题、活跃性问题和性能问题 2021-07-08
并发编程带来的问题,从微观上来说,是可见性,原子性和有序性问题,从宏观角度来说,便是安全性,活跃性和性能问题。何为安全性平时我们常谈到,这个方法是不是线程安全的,这个类是不是线程安全的等等。何为线程安全?便是程序执行结果的正确性,程序执行结果是我们预期的。安全性问题,是因为多个线程同时对共享资源进行读写,由于竞态条件(指程序的执行结果依赖线程执行的顺序),导致数据不一致而产生,那么只要我们不对数据进行共享,或者对共享资源的操作,只能读不能写,和互斥,便能杜绝安全性问题。可以通过Thread Loca原创 2021-07-08 23:54:14 · 110 阅读 · 0 评论 -
“等待-通知机制” 2021-07-08
用synchronized实现等待-通知机制通过java内置的synchronized配合wait(), notify(), notifyAll()即可实现“等待-通知”机制,经典的范式如下,① synchronized(lock) { while(条件不满足) { lock.wait(); } ... lock.notify(); }② synchronized(lock) { while(条件不满足) { lock原创 2021-07-08 22:23:41 · 105 阅读 · 0 评论 -
死锁 2021-07-06
死锁发生的四个条件1. 互斥2. 占用且等待3. 资源不能被抢占4. 循环等待解决死锁,破坏四个条件中的某个1. "互斥"不能被破坏,锁就是互斥的2. 破坏"占用且等待条件",一次性获取需要的所有资源3. java中针对synchronized,破坏"资源不能被抢占"条件不现实,synchronized锁住资源后,资源不会被 其他线程抢占5. 破坏"循环等待"条件,每个线程都需要按照指定顺序申请资源...原创 2021-07-07 23:01:32 · 62 阅读 · 0 评论 -
互斥锁 2021-07-05
count +1 操作是原子操作吗?count +1 不是原子操作。 ????count+1操作过程如下,1. 将count从内存读入cpu寄存器2. cpu寄存器计算,得到结果3. 将结果回写内存或者cpu缓存(缓存机制导致)由于count+1不是原子操作,当多线程操作共享变量count时,因为线程切换带来了原子性问题。根据volatile的经验,我们按需禁用线程切换不就ok了嘛 ????操作系统做线程切换是依赖cpu中断的,所以禁用cpu发生中断就能禁止线程切换禁用线程切换,在早原创 2021-07-07 23:00:01 · 159 阅读 · 0 评论 -
解决可见性和有序性问题 2021-07-02
并发编程bug的源头便是cpu缓存、线程和编译优化带来的可见性、原子性和有序性问题。那么如何解决上述中的可见性和有序性问题?禁用缓存和编译优化,即可保证可见性和有序性,但是程序性能就堪忧了。那么我们按需禁用缓存和编译优化,便是一种合理的方案。于是,Java内存模型出现了。JMM规范了JVM如何提供按需禁用缓存和编译优化的方法。具体来说,包括volatile、synchronized和final三个关键字,以及六项Happens-Before规则。volatilevolatile本意即为禁用cp原创 2021-07-07 22:55:12 · 81 阅读 · 0 评论 -
并发编程bug的源头 2021-07-07
并发编程为什么容易出现问题?它是怎么出问题的?并发程序幕后的故事随着硬件技术的发展,CPU、内存和I/O设备迎来了迅猛的发展。然而发展过程中,一直存在一个核心矛盾,CPU和内存的速度差异,内存和I/O设备之间的速度差异。CPU是天上一天,内存便是地上一年;内存是天上一天,那么I/O设备是地上10年。 木桶效应告诉我们要减小三者之间的差距,才能提高程序的性能。解决方案, 1. CPU增加缓存,以均衡与内存的速度差异 2. 操作系统增加进程、线程,分时复用CPU,进而均衡CP原创 2021-07-07 22:52:42 · 98 阅读 · 0 评论 -
引子--2021-07-01
管程作为一种解决并发问题的模型,是继信号量模型之后的一项重大创新。很多语言都支持管程,搞懂管程,对学习并发编程有很大帮助。然后很多人急于学习Java并发编程技术,却忽略了技术背后的理论和模型,而理论和模型却往往比具体技术更为重要。并发编程可以总结为三个核心问题:分工、同步、互斥。分工指的是如何高效地拆解任务并分配给线程。同步指的是线程之间如何协作,互斥则是保证同一时刻只允许一个线程访问共享资源。Java SDK并发包很大部分内容都按照这三个维度组织,Fork/Join框架是一种分工模式,Count原创 2021-07-07 22:49:39 · 56 阅读 · 0 评论