• Java面试题:什么是死锁?如何手写一个死锁(Dead Lock)


    要想实现一个死锁,首先要明白什么是死锁,我们看一下死锁的定义:

    死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。--百度

    用通俗的话来说就是张三跟李四下饭馆吃饺子,张三拿着醋,李四拿着蒜瓣,张三说李四你给我吃点蒜,李四说,那不行,你得先给我醋,要不然我不给你,张三也不乐意了,说你必须先给我蒜瓣,我再给你醋,这种现象就是死锁。(Dead Lock)

    我们知道使用Synchronize锁两个对象很容易发生这种事,话不多说,直接上代码:

    package Thread;
    
    public class DumplingDeadLockDemo implements Runnable{
        static Object garlic = new Object();
        static Object vinegar = new Object();
        int flag = 0;
        @Override
        public void run() {
            if (flag == 0) {
                synchronized (vinegar) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {return;}
                    System.out.println("我张三正在吃醋,李四你给我点蒜瓣");
                    synchronized (garlic) {
                        System.out.println("我张三终于吃上蒜了,hiahia~");
                    }
                }
            }
            if (flag == 1) {
                synchronized (garlic) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {}
                    System.out.println("俺李四正在吃蒜,张三你给我点醋");
                    synchronized (vinegar) {
                        System.out.println("我李四终于吃上醋了,hiahia~");
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            DumplingDeadLockDemo ZhangSan = new DumplingDeadLockDemo();
            DumplingDeadLockDemo LiSi = new DumplingDeadLockDemo();
            ZhangSan.flag = 0;
            LiSi.flag = 1;
            Thread t1 = new Thread(ZhangSan);
            Thread t2 = new Thread(LiSi);
            t1.start();
            t2.start();
        }
    }
    

    需要注意,新手容易犯的错是把两个synchronized分开写了,那么就永远都不会成了死锁,死锁发生的四个必要条件是:

    1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

    2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

    3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

    4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

    拿我这个例子来说,想要死锁,必须满足:

    互斥性:张三和李四必须吃了醋再吃蒜或者吃了蒜再吃醋,两个事件不可同时发生,否则不满足互斥性自然也不会构成死锁。

    请求和保持条件:至少保证张三拿着醋,李四拿着蒜瓣,但是张三还非得要吃蒜,李四还非得吃醋,否则缺少一个条件都不构成死锁。

    不剥夺条件:张三拿着醋,没完成吃蒜这个事件,李四绝对不能过来抢,否则不满足不剥夺条件。

    环路等待条件:

    一定要构成这种环形等待。

  • 相关阅读:
    ExtJs学习准备工作(二) firebug firefox插件的安装 全新时代
    Hibernate系统中调试SQL方式 全新时代
    Eclipse工程出现红叉导致无法编译的问题 全新时代
    javascript 取table中内容
    Asp.Net中清空所有textbox的几种方法
    SQL Server:使用系统存储过程实现的通用分页存储过程
    C# 检查网络是否连通
    sq分页原理
    SQL Server:日志备份和差异备份还原中的常见问题示例
    javascript:连接数据库
  • 原文地址:https://www.cnblogs.com/taobean/p/12364278.html
Copyright © 2020-2023  润新知