Java死锁

死锁的四个必要条件
1)互斥条件,即某个资源在一段时间内只能由一个线程占有,不能同时被两个或两个以上的线程占有
2)不可抢占条件,线程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者线程自行释放
3)占有且申请条件,线程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外线程占有,此时该线程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。
4)循环等待条件,存在一个线程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个线程循环等待环
解决死锁的办法:加锁顺序,死锁检测

下面通过代码实例来讲解一下如何去写一个死锁代码&如何去解决死锁问题

public class DeadLockTest {
    static class MyTask implements Runnable {
        Object obj1 = "obj1";
        Object obj2 = "obj2";
        int flag;
        private void setFlag(int flag) {
            this.flag = flag;
        }
        @Override
        public void run() {
            if (flag == 1) {
                synchronized (obj1) {
                    System.out.println("locking "+obj1);    //占用obj1
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj2) {
                        System.out.println("使用顺序 obj1 -> obj2");
                    }
                }
            } else if (flag == 2) {
                synchronized (obj2) {
                    System.out.println("locking "+obj2);    //占用obj2
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj1) {
                        System.out.println("使用顺序 obj2 -> obj1");
                    }
                }
            }
        }
    }

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

        MyTask myTask = new MyTask();

        myTask.setFlag(1);
        Thread thread1 = new Thread(myTask);
        thread1.start();

        //保证线程thread1优先执行
        Thread.sleep(100);

        myTask.setFlag(2);
        Thread thread2 = new Thread(myTask);
        thread2.start();
    }
}

通过两个线程去竞争资源从而达到死锁目的
解决方案

        MyTask myTask1 = new MyTask();
        myTask1.setFlag(2);
        Thread thread2 = new Thread(myTask1);
        thread2.start();

理论上是可以解决死锁,但是并没有成功,WTF!想了好久原来是字符串常量的问题,需要通过new String()方式解决,即

        Object obj1 = new String("obj1");
        Object obj2 = new String("obj2");
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本篇结构: 前言 什么是死锁 产生死锁的必要条件 死锁的代码示例 死锁排查 如何避免死锁 总结 一、前言 今天被问...
    w1992wishes阅读 2,425评论 0 0
  • 1、竞态条件: 定义:竞态条件指的是一种特殊的情况,在这种情况下各个执行单元以一种没有逻辑的顺序执行动作,从而导致...
    Hughman阅读 5,132评论 0 7
  • 更多 Java 并发编程方面的文章,请参见文集《Java 并发编程》 死锁 DeadLock 互斥:某个资源不能同...
    专职跑龙套阅读 5,366评论 0 2
  • 死锁的概念 死锁的定义 在多道程序系统中,由于多个进程的并发执行,改善了系统资源的利用率并提高了系统的处理能力。然...
    CodeKing2017阅读 5,435评论 0 4
  • 前两天“调侃”了一位年长朋友的文章。他算小城圈子里有点名气的“乡土文学创作者”。 我们以前互动比较多,近几年联系渐...
    晨风流岚阅读 3,728评论 1 7