Java多线程的死锁与唤醒机制小结

1、多线程死锁问题

因为由于锁的嵌套,就有可能导致死锁现象。

为了防止出现死锁问题,尽量不写嵌套锁,就能避免。

1.1、产生死锁的条件

1.有多把锁
2.有多个线程
3.有同步代码块嵌套

死锁测试:

public class MyThread extends Thread {
    //创建两把锁对象
    static Object objA = new Object();
    static Object objB = new Object();

    @Override
    public void run() {
        while (true) {
            if("小黑".equals(getName())){
                //当前线程是第一条小黑线程
                synchronized (objA){
                    //小黑
                    synchronized (objB){
                        System.out.println("小黑在执行了");
                    }
                }
            }else{
                //当前线程是第二条小美线程
                synchronized (objB){
                    //小美
                    synchronized (objA){
                        System.out.println("小美在执行了~~~~~~~~~");
                    }
                }
            }
        }
    }
}


public class Test {
    public static void main(String[] args) {
        //创建两个线程对象
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        //给两条线程起名字
        t1.setName("小黑");
        t2.setName("小美");

        t1.start();
        t2.start();
    }
}

2、多线程间的通信

多线程中有个状态叫计时等待,可以通过Thread类的方法来进行演示。

// 让当前线程进入到睡眠状态,到毫秒后自动醒来继续执行
public class Test{
  public static void main(String[] args){
    for(int i = 1;i<=5;i++){
      	Thread.sleep(1000);
        System.out.println(i)   
    } 
  }
}

2.1 等待和唤醒(唤醒机制)

Object类的方法

public void wait() : 让当前线程进入到等待状态 此方法必须锁对象调用.

public void notify() : 唤醒当前锁对象上等待状态的线程 此方法必须锁对象调用.

2.2 等待唤醒案例(乘客三窗口上车)

Car类:

package cn.itxiaoli.homework.Demo02;

import java.util.Random;

/**
 * @author xiaoli
 * @className Car
 * @description:
 * @date 2022/3/18 19:22
 */
public class Car {

    // 座位
    public static int seat = 80;

    // 状态 0 前面 1 中 2 后
    public static int flag = 0;

    // 随机对象
    public static Random random = new Random();

    // 锁对象
    public static final Object OBJ = new Object();

}

door1类:

package cn.itxiaoli.homework.Demo02;


/**
 * @author xiaoli
 * @className door1
 * @description:
 * @date 2022/3/18 19:26
 */
public class door1 extends Thread {
    //套路:
    //1.while(true)
    //2.同步代码块
    //3.判断共享数据是否到末位-- 到了末尾
    //4.判断共享数据是否到末位-- 没有到末尾

    @Override
    public void run() {

        while (true) {
            synchronized (Car.OBJ) {
                // 座位为0时 跳出死循环
                if (Car.seat == 0) {
                    break;
                }

                // 0 前门上车
                if (Car.flag == 0) {
                    // 修改三个门的状态,利用随机数达到模拟现实生活中随机上车(0,1,2)
                    Car.flag = Car.random.nextInt(3);
                    // 此时已经上车一人做减减操作
                    Car.seat--;
                    System.out.println(getName() + "门上车---还剩" + Car.seat + "个座位");
                    // 唤醒等待的其他车门线程
                    //细节1:必须用wait方法,跟锁进行绑定,此时锁才知道要唤醒哪些线程
                    //细节2:如果没有线程在等待,那么也可以唤醒,没有任何问题。
                    Car.OBJ.notifyAll();
                } else {
                    try {
                        // 当其他车门线程执行到这行代码的时候,就会等待并且跟前面锁对象绑定在一起
                        Car.OBJ.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

door2类:

package cn.itxiaoli.homework.Demo02;


/**
 * @author xiaoli
 * @className door2
 * @description:
 * @date 2022/3/18 19:26
 */
public class door2 extends Thread {
    @Override
    public void run() {

        while (true) {
            synchronized (Car.OBJ) {
                if (Car.seat == 0) {
                    break;
                }

                // 中门上车
                if (Car.flag == 1) {
                   // 随机上车
                    Car.flag = Car.random.nextInt(3);
                    Car.seat--;
                    System.out.println(getName() + "门上车---还剩" + Car.seat + "个座位");
                    Car.OBJ.notifyAll();
                } else {
                    try {
                        Car.OBJ.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

door3类:

package cn.itxiaoli.homework.Demo02;


/**
 * @author xiaoli
 * @className door3
 * @description:
 * @date 2022/3/18 19:27
 */
public class door3 extends Thread {
    @Override
    public void run() {
        while (true) {
            synchronized (Car.OBJ) {
                if (Car.seat == 0) {
                    break;
                }

                // 后门上车
                if (Car.flag == 2) {
                    Car.flag = Car.random.nextInt(3);
                    Car.seat--;
                    System.out.println(getName() + "门上车---还剩" + Car.seat + "个座位");
                    System.out.println("-----------------------");
                    Car.OBJ.notifyAll();
                } else {
                    try {
                        Car.OBJ.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

测试类:

package cn.itxiaoli.homework.Demo02;

/**
 * @author xiaoli
 * @className Test
 * @description:
 * @date 2022/3/18 19:27
 */
public class Test {
    public static void main(String[] args) {
        // 三个门的线程对象
        door1 door1 = new door1();
        door2 door2 = new door2();
        door3 door3 = new door3();

        // 设置车门线程名字
        door1.setName("前");
        door2.setName("中");
        door3.setName("后");

        // 开启线程
        door1.start();
        door2.start();
        door3.start();


    }
}

注意:

​ 只要用wait和notify或者notifyAll就是等待唤醒机制。(根据输出结果的要求,破坏了多线程的随机性,相当于制订了执行了一种规则)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值