你是否因为写出死锁导致半夜加班,扣绩效?你是否为小白程序员,还没有接触过并发编程不知道什么死锁,你是否希望通过并发编程这块突破自己的瓶颈,在新的一年挑战高薪?那么JAVA并发编程中的死锁是你避不开的 。
在通过redis或者zookeeper实现分布式锁时也可能出现死锁,本篇文章从Java线程入手,解密以下几点:
- 什么是死锁,死锁如何产生
- 通过有趣的案例实现死锁,并分析原因
- 分析死锁产生的四个必要条件,并且解决死锁
- 通过Java自带工具检测和定位死锁位置
- 通过银行家算法,规避死锁问题
我们来看一个死锁例子:
公司需要有工作经验的员工,而刚毕业的小伙伴需要工作来获得工作经验,这样企业和应届生之间就产生了死锁现象
这样的例子还有很多,比如:两辆车过桥
电影中的经典情节:我要的货呢,你带钱没有,最后一手交钱一手交货
所谓的死锁其实是一种现象,就是两个或两个以上线程的多线程情况下,多个线程同时被阻塞,它们中的一个或全部都在等待某一锁资源的释放,由于线程被无期限的阻塞,因此程序不会继续执行,表现为卡住不动 。
如:线程1和线程2的运行都需要A资源和B资源,此时线程1获取了A资源,线程2获取到了B锁,此时线程1获取不到B锁和线程2获取不到A锁,导致两个线程彼此僵持!
多把锁场景之前文章中的案例都是使用一把锁,死锁是线程需要多把锁才会出现,那么什么场景下需要多把锁呢?
案例家中住着张三和翠花夫妻二人,家庭条件一般,只有一个厨房,希望实现翠花做饭和张三洗菜互不相干
一把锁解决分析:
- 定义一个厨房类,两个功能,分别为洗菜和做饭【煮粥不是炒菜】
- 定义一把锁,直接将厨房锁上
- 假设洗菜需要1秒,做饭需要2秒
- 洗菜和做饭时使用唯一的一把厨房锁,将整个厨房锁上,实现互不打扰
package com.tianzhen.thread;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;public class KitchenRoom {// 锁对象public Object lock = new Object();// 洗菜public void washing() {// 锁住房间synchronized (lock) {// 输出开始时间 + 操作System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss SSS")) + ":洗菜");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}// 做饭【煮粥】public void cook() {// 锁上房间synchronized (lock) {// 输出开始时间 + 操作System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss SSS")) + ":做饭");try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
运行结果:文章插图
使用一把锁的时候性能较低,因为锁的范围太大了,直接将厨房锁住,只需将房间内的每一个功能单独锁起来即可,比如:单独将洗菜,做饭,使用冰箱锁住,不能多人同时使用,应该将锁细化,这样同一个房间就可以同时做很多工作,厨房的利用率就会上来,洗菜和做饭可以同步进行,这样是不就可以早点吃上美味了呢!
厨房改造:
package com.tianzhen.thread;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;public class KitchenRoom {// 洗菜锁public Object washLock = new Object();// 做饭锁public Object cookLock = new Object();// 洗菜public void washing() {// 使用洗菜锁synchronized (washLock) {System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss SSS")) + ":洗菜");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}// 做饭public void cook() {// 使用做饭锁synchronized (cookLock) {System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss SSS")) + ":做饭");try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 怎么看内存条频率是3200还是2666 怎么看内存条频率
- sd内存条?现在SD内存卡最大是多少G?
- 内存卡数据恢复软件免费 内存卡数据恢复软件
- 凯迪拉克流媒体内存卡;什么是流媒体音乐
- 怎样清理电脑内存垃圾 怎样清理电脑内存
- 一招修复内存不能read桌面不显示 应用程序错误
- 相机内存卡数据恢复软件免费版 相机内存卡数据恢复
- 长月烬明|首播6集收视率飙升,评分剑指8.8,强大的演员阵容十分令观众期待
- 32位系统内存限制解决 32位系统内存
- 360手机病毒清理 清理一下内存