下面这两段代码,一个实现Runnable接口,一个继承Thread类,前面的能正常交替输出
但是后面继承Thread的运行会死锁,没想明白为什么会死锁,求指教
public class Test3 {
static class MyRun implements Runnable {
static int i = 0;
@Override
public synchronized void run() {
for (int j = 0; j < 10; j++) {
if(i%2==0)
System.out.println(Thread.currentThread().getName()+":A");
else
System.out.println(Thread.currentThread().getName()+":B");
i++;
this.notifyAll();
try {
if(i>=19)
Thread.sleep(10);
else
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
MyRun myRun = new MyRun();
Thread a = new Thread(myRun);
Thread b = new Thread(myRun);
a.start();
b.start();
}
}
public class Test3 {
static class MyRun extends Thread {
static int i = 0;
@Override
public synchronized void run() {
for (int j = 0; j < 10; j++) {
if(i%2==0)
System.out.println(Thread.currentThread().getName()+":A");
else
System.out.println(Thread.currentThread().getName()+":B");
i++;
this.notifyAll();
try {
if(i>=19)
Thread.sleep(10);
else
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
MyRun m1 = new MyRun();
MyRun m2 = new MyRun();
m1.start();
m2.start();
}
}
int i = 0;移到run方法中试试,去掉static
第一个例子是一把锁,一把锁的持有者是new MyRun一个实例,第一个等待锁唤醒,第二个会把第一个锁唤醒,因为是同一把锁。
第二个例子是两把锁,两把锁的持有者分别是两个new MyRun实例,两个线程独立的锁,所以都在等待,不会被唤醒
这个不是死锁,后面的代码两个线程使用的不是同一把锁,运行暂停是因为this.wait();让自己的线程一直wait,而没法唤醒。
用 this 作为锁是不行的,一旦调用 this 锁后,当前线程就挂起了,再也不会有其他线程能够唤醒它了。
解决办法,定义一个锁对象,由调用者传入,同步时用该锁。并发编程的相关经验,有需要可以看看这篇:并发编程入门指南
另外,我回答了很多类似的问题,近期最详细的一条,参考下这个:多线程编程 notify 不起作用的原因分析
修改代码为:
static class MyRun extends Thread {
private Object lock = null;
public MyRun(Object lock){
this.lock = lock;
}
static int i = 0;
@Override
public void run() {
synchronized (lock) {
for (int j = 0; j < 10; j++) {
if(i%2==0)
System.out.println(Thread.currentThread().getName()+":A");
else
System.out.println(Thread.currentThread().getName()+":B");
i++;
lock.notifyAll();
try {
if(i>=19)
Thread.sleep(10);
else
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
Object lock = new Object();
MyRun m1 = new MyRun(lock);
MyRun m2 = new MyRun(lock);
m1.start();
m2.start();
}