死锁、线程bing

上一篇

前言

定义:在两个或者两个以上的线程运行中,因为资源抢占而造成线程一直等待的问题。
检测工具:jconsole、jmc、jvisualvm
位置:
JDK8\bin

造成死锁的4个条件:

死锁代码:
在这里插入图片描述

1.互斥条件:当资源被一个线程拥有之后,就不能被其它的线程拥有了。(不可更改)
⒉.请求拥有条件:当一个线程拥有了一个资源之后又试图请求另一个资源。(可以解决)
3.不可剥夺条件:当一个资源被一个线程拥有之后,如果不是这个线程主动释放此资源的情况下,其他线程不能拥有此资源。(不可更改)
4.环路等待条件:两个或两个以上的线程在拥有了资源之后,试图获取对方资源的时候形成了一个环路。(可以解决)

解决

解决造成死锁的4个条件中的请求拥有条件或者环路等待条件

死锁解决的问题最有效的解决方案:控制加锁的顺序。解决环路等待条件。

线程通讯

wait【休眠线程】/notify【唤醒一个线程】/notifyAll【唤醒全部线程】
所谓的线程通讯指的是在一个线程中的操作可以影响另一个线程。

wait 注意事项:

1.wait方法在执行之前必须先加锁,也就是说 wait方法一定要配合 synchronized一起使用。
2.wait和notify 在配合synchronized 使用时,一定要注意要使用同一把锁。
在这里插入图片描述
3.wait 和 notify在配合使用时,一定要操作同一把锁。
错误的例子:
在这里插入图片描述

wait和notify / notfiyAll 的问题:
不能指定唤醒的线程。

wait在不传递任何参数的情况下会进入waiting状态,当wait里面时候这了一个大于0的整数时,它会进入limed_waiting。
在这里插入图片描述
在这里插入图片描述

wait和sleep区别

相同点:
1.wait和 sleep都是让线程进行休眠状态。
2.wait和 sleep在执行的过程中都可以接收到终止线程执行的通知。
不同点:
1.wait使用必须配合synchronized一起使用,而sleep不用。
2.wait会释放锁,而sleep不会释放锁。
3.wait是0bject 的方法,而sleep是Thread(线程)的方法。
4.默认情况下 wait(不传递任何参数或者是参数为0的情况下)它会进入 waiting 状态,而sleep会进入timed waiting状态。
5.使用 wait 时可以主动的唤醒线程,而使用sleep 时不能主动唤醒线程。

sleep(0) vs wait(0)区别

1.sleep(0)表示过0毫秒之后继续执行,而wait(0)表示一直休眠。2.sleep(0)表示重新触发一次CPU竞争。

为什么wait会释放锁, 而sleep不会释放锁

答: sleep必须要传递一个最大等待时间的,也说 sleep是可控的(对于时间层面来讲),而 wait 是可以不传递传输,从设计层面来讲如果让 wait这个没有超时等待时间的机制不释放锁的话,那么线程可能会一直阻塞,而sleep 就不存在这个问题。

为什么wait 是0bject的方法,而sleep是Thread 的方法

答: wait需要操作锁,而锁是属于对象级别(所有的锁都是放在对象头当中),它不是线程级别,一个线程中可以有多把锁,为了灵活起见,所以就将 wait放在0bject 当中。

解决wait/notify 随机唤醒的问题—— LockSupport park ()/unpark(线程)

与wait异同

   public static void main(String[] args) throws InterruptedException {


        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 让线程进行休眠
                LockSupport.park();
                System.out.println("唤醒 t1");
            }
        }, "t1");


        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 让线程进行休眠
                LockSupport.park();
                System.out.println("唤醒 t2");
            }
        }, "t2");

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                // 让线程进行休眠
                LockSupport.park();
                System.out.println("唤醒 t3");
            }
        }, "t3");

        t1.start();
        t2.start();
        t3.start();

        LockSupport.unpark(t2);

    }

在这里插入图片描述

LockSupport 虽然不会报Interrupt 的异常,但依旧可以监听到线程中止的指令。
测试例子:

   public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("park 之前 Interrupt 状态:" +
                        Thread.currentThread().isInterrupted());
                // 线程进入休眠
                LockSupport.park();
                System.out.println("park 之后 Interrupt 状态:" +
                        Thread.currentThread().isInterrupted());
            }
        }, "t1");
        // 启动线程
        t1.start();

        Thread.sleep(100);
        // 中止线程
        t1.interrupt();
        // 唤醒线程 t1
        LockSupport.unpark(t1);
    }

在这里插入图片描述
在这里插入图片描述
sleep wait park 区别
下一篇

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月屯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值