Java多线程中的死锁

mac2024-03-17  31

前言

本篇博文是对Java多线程中的死锁的实现介绍。

多线程的死锁

1.死锁的原因:

首先,产生死锁需要的两个锁对象(假设A,B),当两个线程同时运行时,并同时使用了两个锁对象;简单说就是锁A等待锁B释放,而锁B也在等待锁A释放,这样就产生了所谓的死锁,当然死锁的几率并不是百分之百,而是有一定几率的;原因的CPU在线程之间切换是没有规律的,所以产生死锁,具体看CPU的调节度

2.使用一个例子来更深刻的了解死锁

演示死锁:

比如我现在有两个锁对象LOCK_A,LOCK_B(在Java中所有的对象都是可以做为锁对象的这里的两个锁对象都是Object),我把两个锁对象比喻成两根筷子,只有拿到两个筷子时才能进食(对于一个线程而言同时满足)

3.代码

package com.jimmy.demo; /** * @Author ScholarTang * @Date 2019/10/31 8:18 PM * @Desc 演示死锁 * * 在这个例子中,我会把两都是Object的锁对象比喻成两个筷子(A,B) * 当同时拿到A,B两根筷子时即可进食 * */ public class Deadlock { //定义两常量对象分别代表锁A,和锁B对象 public static final Object LOCK_A = new Object(); public static final Object LOCK_B = new Object(); public static void main(String[] args) { //线程一 new Thread(() -> { System.out.println("Thread a start"); synchronized (LOCK_A) { System.out.println("Thread a :拿到筷子A,等待筷子B"); synchronized (LOCK_B) { System.out.println("Thread a : 拿到筷子B,开始进食"); } } }).start(); //线程二 new Thread(() -> { System.out.println("Thread b start"); synchronized (LOCK_B) { System.out.println("Thread b :拿到筷子B,等待筷子A"); synchronized (LOCK_A) { System.out.println("Thread b :拿到筷子A,开始进食"); } } }).start(); } }

3.1.代码分析

启动了两个线程,两个线程中都有两个同步锁,第一个线程时锁B在锁A里面,第二个线程时锁A在锁B里面,两个锁交叉使用。在执行到代码块时,锁对象已经被锁住,代码块执行完锁对象释放

3.2.测试结果

注意:不是每次运行都会出现死锁现象,这是本人运行多次才出现的死锁现象

3.3.根据测试结果分析

CPU时在线程之间高速切换的,我们来分析一下这段代码出现的死锁情况

1.当第一个线程执行到第一个同步代码块时,LOCK_A对象已经被锁住;CPU快速切换到第二个线程,执行第一个代码块LOCK_B对象被锁住

2.CPU又切回到第一个线程,程序无法执行,第一个线程现在要执行第二个同步代码块,此时LOCK_B对象已经被锁住,无法往下面执行;CPU切换到线程二,同理往下执行,而LOCK_A也被锁住,此时:两个线程相互等待对方锁释放,而两边都释放不了,就产生了死锁

最新回复(0)