java多线程死锁学习

什么是线程死锁

定义

死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

举例

假设有两个孩子分别为孩子A和孩子B,相当于两个线程,还有两个玩具,一个是苹果,一个是香蕉,一开始孩子A拿的是苹果,孩子B拿的是香蕉,之后过了一段时间,孩子A想要玩香蕉,孩子B想要玩苹果,但是他们都不愿意放下手中的玩具,结果就会导致双方都想要对方的玩具,但是又不放弃现在持有的玩具,就只能导致两方都在等待了,也就是我们所说的死锁了

package deadLock;
/**
 * @Author: WalkerShen
 * @DATE: 2022/3/15
 * @Description: 死锁
 **/
public class DeadLockDemo {

    /**
     * 模拟场景:
     * 线程0 获取资源1 休眠 获取资源2
     * 线程1 获取资源2 休眠 获取资源1
     */

    //定义两个资源
    //资源1
    private final static String apple="a";
    //资源2
    private final static String banana="b";

    public static void main(String[] args) {



        //定义线程A
        new Thread(()->{
            //使用synchronized进行加锁资源1
            synchronized (apple){
                System.out.println(Thread.currentThread().getName()+"获取苹果");
                //这里休眠1秒,确保线程B对资源2进行持有
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"等待获取香蕉");
                //此时,未曾释放资源1,但是想获取资源2的锁,但是资源2的锁已经被线程B持有,就会导致两方互相等待对方资源,导致死锁
                synchronized (banana){
                    System.out.println(Thread.currentThread().getName()+"获取香蕉");
                }
            }
        },"孩子A").start();


        //定义线程B
        new Thread(()-> {
            //使用synchronized进行加锁资源2
            synchronized (banana) {
                System.out.println(Thread.currentThread().getName() + "获取香蕉");
                //这里休眠1秒,确保线程A对资源1进行持有
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //加锁资源1
                System.out.println(Thread.currentThread().getName()+"等待获取苹果");
                synchronized (apple) {
                    System.out.println(Thread.currentThread().getName() + "获取苹果");
                }
            }
        },"孩子B").start();
    }

}

执行结果:

孩子A获取苹果
孩子B获取香蕉
孩子B等待获取苹果
孩子A等待获取香蕉

形成死锁的四个必要条件是什么

互斥条件:

  • 线程(进程)对于所分配到的资源具有排它性,
  • 即一个资源只能被一个线程(进程)占用,直到被该线程(进程)释放

请求与保持条件:

  • 一个线程(进程)因请求被占用资源而发生阻塞时,对已获得的资源保持不放。

不剥夺条件:

  • 线程(进程)已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。

循环等待条件:

  • 当发生死锁时,所等待的线程(进程)必定会形成一个环路(类似于死循环),造成永久阻塞

如何避免线程死锁 3`

我们只要破坏产生死锁的四个条件中的其中一个就可以了。

破坏互斥条件

这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)

破坏请求与保持条件

一次性申请所有的资源。

package deadLock;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: WalkerShen
 * @DATE: 2022/3/15
 * @Description: 破坏请求和保持
 **/
public class BreakRequestAndKeep {


    /**
     * 孩子A和孩子B分别一次性持有所有的资源
     * 这里是将资源都放在了一个数组里面,然后进行持有
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");

        new Thread(()->{
            synchronized (list){
                System.out.println(Thread.currentThread().getName()+"持有苹果和香蕉");
            }
        },"孩子A").start();


        new Thread(()->{
            synchronized (list){
                System.out.println(Thread.currentThread().getName()+"持有苹果和香蕉");
            }
        },"孩子B").start();
    }
}

破坏不剥夺条件

占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。

破坏循环等待条件

靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

案例

这里先双方都先获取苹果,之后再获取香蕉
假设孩子A先获取到苹果,那么孩子B就会等待
之后孩子A会在持有苹果的过程中再去获取香蕉,获取完香蕉之后,会将两个玩具都放回原处,之后孩子B就可以去拿苹果和香蕉了

package deadLock;
/**
 * @Author: WalkerShen
 * @DATE: 2022/3/15
 * @Description: 破坏循环等待
 **/
public class BreakCircularWait {

    //定义两个资源
    //资源1
    private final static String apple="apple";
    //资源2
    private final static String banana="banana";

    public static void main(String[] args) {


        new Thread(()->{
            synchronized (apple){
                System.out.println(Thread.currentThread().getName()+"获取"+apple);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"等待"+banana);
                synchronized (banana){
                    System.out.println(Thread.currentThread().getName()+"获取"+banana);
                }
            }
        },"孩子A").start();


        new Thread(()-> {
            synchronized (apple) {
                System.out.println(Thread.currentThread().getName() +"获取"+ banana);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"等待"+banana);
                synchronized (banana) {
                    System.out.println(Thread.currentThread().getName() +"获取"+ banana);
                }
            }
        },"孩子B").start();
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 1、什么是死锁? ​ 死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的互相等待的现象,在无外力...
    先弓阅读 100评论 0 0
  • 1. 线程和进程的区别? 它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会...
    Darkmoss阅读 521评论 0 0
  • [TOC] 0 前言 为什么需要学习并发编程? 大厂JD硬性要求,也是高级工程师必经之路,几乎所有的程序都需要并发...
    憩在河岸上的鱼丶阅读 440评论 0 3
  • 进程是指运行中的应用程序,每个进程都有自己独立的地址空间; 线程是进程中执行运算的最小单位,一个进程中可以有多个线...
    SuperFatso阅读 126评论 0 2
  • 1.线程同步 多线程引发的安全问题 一个非常经典的案例,银行取钱的问题。假如你有一张银行卡,里面有5000块钱,然...
    容华谢后阅读 1,332评论 5 13