(学习笔记)死锁

死锁

怕艾兵豪斯的遗忘曲线提前来,先mark一下

简单的说:两个线程在持有自己的锁的情况下需要彼此手中的锁(中的资源),彼此不放手,那么就一直在等待对方释放手中的锁,永远的等待~导致了死锁
示例:

public class Test {
    public static void main(String[] args) {
        // 死锁演示
        MyThread myThread = new MyThread();
        Thread thread = new Thread(myThread, "1");
        Thread thread1 = new Thread(myThread, "2");
        thread.start();
        thread1.start();
    }
    static class MyThread implements Runnable {
    // 同步代码块中要保证锁对象一致,否则跟没有锁一样,达不到数据同步的效果
        Object lock = new Object();
        @Override
        public void run() {
                if (Thread.currentThread().getName().equals("1")) {
                    synchronized (lock) {
                        try {
    // 让线程睡一下的目的是为了保证后进行的线程能拿到锁
    (cpu处理太快,也即是后执行的线程还没拿到锁的时候,先执行的线程就已经执行完毕,
    并将资源和锁释放了,后执行的线程就会照常执行)
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        say("1");
                    }
                } else {
                    say("2");
                }
        }
        private synchronized void say(String name) {
            synchronized (lock) {
            // 同上
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(name+"我执行了");
            }
        }
    }
}

这里要注意一下:测试死锁的显示,要在psvm主方法的环境下运行才能看到死锁的发生,如果是使用单元测试来测试死锁则会没有效果,具体原因目前还不清楚

发生条件:
①:互斥:一个线程获得资源后,另一个需要相同资源的线程只能等待(阻塞)
②:线程中的锁只能通过自己释放,外界无法干预
③:请求与保持:线程未完成前,自己持有的锁(资源)也不会主动释放
④:线程之间循环等待
(死循环,这里联想到了jdk1.7中的HashMap的死循环,在1.8中已经解决(通过加锁))
满足上面的所有条件就会发生死锁
如何避免:个人认为上述条件之一不成立即可
ps:可重入锁可以有效的解决该问题:线程1如果已经获得过一次锁,资源就会记录该线程,下一次又来获取锁(资源)的时候,如果发现其他的线程也在竞争同一个锁(资源),为了避免死锁的发生,线程1就会主动放弃该锁,以及自己持有的资源,让其他线程先使用,待有空当之后再完成自己的事情,从而避免死锁,当中保持自旋。
有一个比较粗俗的例子:小明去上厕所,发现厕所里面已经满了,要么在厕所里等,要么在外面等,如果在里面等,不仅会影响后面进来的人,还要感受“芳香”,实在没有必要,不如直接在外面等,玩会手机/抽烟,一旦有人出来再进去就好。
2019.12.17:补充,这里重新定义对可重入锁的概念:第一次看的时候以为就是上面的定义,但最近重新了解了可重入锁之后,发现好像和一开始认识的可重入锁截然不同。
就目前来说,我对可重入锁(又称递归锁)的理解是:当对象中的多个方法都存在锁机制时,当某一线程抢夺到了最外层的方法的锁时,它就能顺理成章的接着进行内层中还存在了锁的代码块,也就是一方通行!
感想:看着容易理解,但实际敲一遍效果和看一遍还是有天壤之别的,这也说明了理论和实践同样重要,希望能坚持每天写!
ps:还在学习中,希望大牛们发现上面理解和代码中存在的问题能在评论中指出~感谢
(没有感情的复制怪~)

引用:https://blog.csdn.net/lixinkuan328/article/details/94416483

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

淳杰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值