Java编程语言的三大特点,注意不是面向对象语言的三大特性(封装,继承,多态)。
- 异常处理
- 垃圾回收
- 多线程
本文聊聊如何实现一个死锁,在Java里我们可以给对象加锁通过sychronized关键字。
死锁的条件是相互请求对方所占用的资源。我们可以让两个线程分别占用一个对象,并请求另一个线程所占用的对象。这样达到死锁的目的。
class Ob implements Runnable {
// 定义两个对象
Object o1 = new Object();
Object o2 = new Object();
// 状态码,控制线程锁哪个对象
int status;
Ob(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public void run() {
if(status == 1) {
// 3给o1加锁
synchronized (o1) {
Thread currentThread = Thread.currentThread();
System.out.println(currentThread.getName() + " locked -- >> o1");
System.out.println(currentThread.getName() + " sleep 1s ...");
try {
// 4锁住对象1,然后休眠,等待o2被锁
Thread.sleep(550); // 这里时间 > 500 + thread2启动线程,否则thread2还来不及锁住o2
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(currentThread.getName() + " gets up");
// 这个时候请求 o2
synchronized (o2) {
System.out.println(currentThread.getName() + "want to lock o2");
}
}
}
if(status == 2) {
// 7锁住o2
synchronized (o2) {
Thread currentThread = Thread.currentThread();
System.out.println(currentThread.getName() + " locked -- >> o2");
// 8 o1 被锁,发生死锁
synchronized (o1) {
System.out.println(currentThread.getName() + "want to lock o1");
}
}
}
System.out.println("death locked ...this println don't execute forever..");
}
}
主线程这样去调用:
Ob ob = new Ob(1);
Thread thread = new Thread(ob,"thread ---- 1");
thread.start();
// 1如果不让主线程暂停,则在启动thread之前,已经修改了ob的status = 2,只会去锁对象2了,并且执行两次
try {
// 2休眠500ms,让thread启动,否则还还没启动ob.status 就被改变了
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 5thread.start这个时候的状态肯定锁住了o1
ob.setStatus(2);
Thread thread2 = new Thread(ob, "thread ----- 2");
thread2.start(); // 6这个时候请求线程去锁o2