死锁产生的原因以及手写死锁
产生死锁的原因可归结为如下两点:
a. 竞争资源
系统中的资源可以分为两类:
- 可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺
- 不可剥夺资源,当系统把这类资源分配给某进程后,只能等进程用完后自行释放
产生死锁中的竞争资源之一指的是竞争不可剥夺资源
产生死锁中的竞争资源另外一种资源指的是竞争临时资源,通常消息通信顺序进行不当,则会产生死锁
b. 进程间推进顺序非法
若P1保持了资源R1,P2保持了资源R2,当P1需要继续占用R2且需要占用R1时两个线程均被阻塞,于是发生进程死锁
死锁产生的4个必要条件:
- 互斥条件:进程要求对所分配的资源进行排它性控制
- 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放
- 不剥夺条件:进程已获得的资源在未使用完之前,只能在使用完时由自己释放
- 环路等待条件:在发生死锁时,必然存在一个进程–资源的环形链。
手写死锁
public class DeadLock {
public static void main(String... args) {
Thread t1 = new Thread(new MyDeadLock(true));
Thread t2 = new Thread(new MyDeadLock(false));
t1.start();
t2.start();
}
}
class MyDeadLock implements Runnable {
private boolean flag;
// 使用static为静态变量, 内存在方法区中,
// 方法区中的对象是线程共享的,所以会引发死锁
// 不加static存在堆上
// 堆上的对象是线程私有的, 下面的写法就不会造成死锁
private static Object o1 = new Object();
private static Object o2 = new Object();
public MyDeadLock(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (this.flag) {
synchronized (o1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("e.printStackTrace();");
}
synchronized (o2) {
System.out.println("嘿嘿嘿");
}
}
} else {
synchronized (o2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("e.printStackTrace();");
}
synchronized (o1) {
System.out.println("哈哈哈");
}
}
}
}
}
其他写法
import java.security.PublicKey;
public class DeadLock1 {
public static void main(String... args) {
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(new MyDeadLock1(true, o1, o2));
Thread t2 = new Thread(new MyDeadLock1(false, o1, o2));
t1.start();
t2.start();
}
}
class MyDeadLock1 implements Runnable {
private boolean flag;
private Object o1;
private Object o2;
public MyDeadLock1(boolean flag, Object o1, Object o2) {
this.flag = flag;
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
if (this.flag) {
synchronized (o1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("e.printStackTrace();");
}
synchronized (o2) {
System.out.println("嘿嘿嘿");
}
}
} else {
synchronized (o2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("e.printStackTrace();");
}
synchronized (o1) {
System.out.println("哈哈哈");
}
}
}
}
}
还没有评论,来说两句吧...