回顾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