编程语言
首页 > 编程语言> > 回顾java死锁

回顾java死锁

作者:互联网

认识死锁

多个进行相互等待对方资源,在得到所有资源继续运行之前,都不会释放自己已有的资源,这样造成了循环等待的现象,称为死锁。

package com.egar.launcher;

/**
 * @des: Created by ybf
 * @version: 3.3.2
 * @date: 2019/9/5 14:53
 * @see {@link }
 */
public class Testjava {
    private static Object resource1 = new Object();//资源 1
    private static Object resource2 = new Object();//资源 2

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource1) {
                    System.out.println(Thread.currentThread() + "get resource1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread() + "waiting get resource2");
                    synchronized (resource2) {
                        System.out.println(Thread.currentThread() + "sync get resource2");
                    }
                }
            }
        },"线程1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource2) {
                    System.out.println(Thread.currentThread() + "get resource2");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread() + "waiting get resource1");
                    synchronized (resource1) {
                        System.out.println(Thread.currentThread() + "sync get resource1");
                    }
                }
            }
        },"线程2").start();
    }
}
Output:
Thread[线程1,5,main]get resource1
Thread[线程2,5,main]get resource2
Thread[线程1,5,main]waiting get resource2
Thread[线程2,5,main]waiting get resource1

线程 A 通过 synchronized (resource1) 获得 resource1 的监视器锁,然后通过 Thread.sleep(1000);让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。上面的例子符合产生死锁的四个必要条件。
(我中有你,你中有我,没有释放资源,互相持有产生死锁)

1.互斥条件:该资源任意一个时刻只由一个线程占用。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

对线程2 进行修改:
     new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource1) {
                    System.out.println(Thread.currentThread() + "get resource1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread() + "waiting get resource1");
                    synchronized (resource2) {
                        System.out.println(Thread.currentThread() + "sync get resource2");
                    }
                }
            }
        },"线程2").start();
Output:
Thread[线程1,5,main]get resource1
Thread[线程1,5,main]waiting get resource2
Thread[线程1,5,main]sync get resource2
Thread[线程2,5,main]get resource1
Thread[线程2,5,main]waiting get resource1
Thread[线程2,5,main]sync get resource2

Process finished with exit code 0

** 线程 1 首先获得到 resource1 的监视器锁,这时候线程 2 就获取不到了。然后线程 1 再去获取 resource2 的监视器锁,
可以获取到。然后线程 1 释放了对 resource1、resource2 的监视器锁的占用,线程 2 获取到就可以执行了。这样就破坏了破坏循环等待条件,因此避免了死锁。**

Sleep() 和wait() 区别

1.sleep方法没有释放锁,wait方法释放了锁
2.都可以暂停线程执行
3.wait通常被用于线程交互,sleep通常被用于暂停执行
4.wait调用后,线程不会自动唤醒,需要别的线程调用同一个对象上的notify() 或者 notifyAll() 方法。
sleep() 方法执行完成后,线程会自动苏醒。或者可以使用wait(long timeout)超时后线程会自动苏醒。

为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?

调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。

标签:java,回顾,Thread,get,死锁,线程,main,resource1,resource2
来源: https://blog.csdn.net/weixin_38148680/article/details/100559379