慕课网高并发实战(十)- 死锁

死锁发生的必要条件


慕课网高并发实战(十)- 死锁_第1张图片



package com.mmall.concurrency.example.deadLock;

import lombok.extern.slf4j.Slf4j;

/**

* 一个简单的死锁类

* 当DeadLock类的对象flag==1时(td1),先锁定o1,睡眠500毫秒

* 而td1在睡眠的时候另一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500毫秒

* td1睡眠结束后需要锁定o2才能继续执行,而此时o2已被td2锁定;

* td2睡眠结束后需要锁定o1才能继续执行,而此时o1已被td1锁定;

* td1、td2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。

*/

// 互斥条件:o1,02排他性请求,排他性锁定,只有一个进程使用

// 请求和保持条件:请求了o1,保持了o2;另外一个是请求了o2,保存了o1

// 不剥夺条件:请求了o1后,别的资源就不能抢走他的资源

//  环路等待条件:占了o1,等待o2; 第二个是占了o2,等待o1;

@Slf4j

public class DeadLockimplements Runnable {

public int flag =1;

    //静态对象是类的所有对象共享的

    private static Objecto1 =new Object(), o2 =new Object();

    @Override

    public void run() {

log.info("flag:{}", flag);

        if (flag ==1) {

synchronized (o1) {

try {

Thread.sleep(500);

                }catch (Exception e) {

e.printStackTrace();

                }

synchronized (o2) {

log.info("run1");

                    log.info("1");

                }

}

}

if (flag ==0) {

synchronized (o2) {

try {

Thread.sleep(500);

                }catch (Exception e) {

e.printStackTrace();

                }

synchronized (o1) {

log.info("run2");

                    log.info("0");

                }

}

}

}

public static void main(String[] args) {

DeadLock td1 =new DeadLock();

        DeadLock td2 =new DeadLock();

        td1.flag =1;

        td2.flag =0;

        //td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。

//td2的run()可能在td1的run()之前运行

        new Thread(td1).start();

        new Thread(td2).start();

    }

}

避免死锁条件

 1 加锁顺序,对象的加锁顺序应该一样

2  加锁时间,超过时间后就放弃该锁的请求,并释放自己占用的锁

3 死锁检测


检查到死锁的操作:

1 释放所有的锁,回退,并且等待一段时间后 重试

2 设置线程优先级(随机的优先级)



慕课网高并发实战(十)- 死锁_第2张图片


慕课网高并发实战(十)- 死锁_第3张图片
慕课网高并发实战(十)- 死锁_第4张图片

10.4 HashMap 与ConcurrentHashMap

hashMap 线程不安全主要体现在:resize()会出现死循环使用迭代器的时候出现

ConcurrentModificationException,这就是所谓fail-fast策略

单线程下的扩容


慕课网高并发实战(十)- 死锁_第5张图片

你可能感兴趣的:(慕课网高并发实战(十)- 死锁)