谁能帮我解释下以下这段代码是怎么运行的?没有理解,怎么就造成了死锁呢?synchronized关键字到底是锁DemoA还是锁FunA或者锁住的是FunA+Fun2?
按我的理解是应该打印:
DemoA--->进去DemoA中的FunA(DemoB db)方法!!!!!
DemoB--->进去DemoB中的void fun2()方法!!!!!
DemoB--->进去DemoB中的funB(DemoA da)方法!!!!!
DemoA--->进去DemoA中的void fun2()方法!!!!!
实际上打印的内容是:
DemoA--->进去DemoA中的FunA(DemoB db)方法!!!!!
DemoB--->进去DemoB中的funB(DemoA da)方法!!!!!
以下代码出自李兴华多线程第四讲~class DemoA { public synchronized void funA(DemoB db){
System.out.println("DemoA--->进去DemoA中的FunA(DemoB db)方法!!!!!");
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
db.fun2();
}
public synchronized void fun2(){
System.out.println("DemoA--->进去DemoA中的void fun2()方法!!!!!");
}
}class DemoB {
public synchronized void funB(DemoA da){
System.out.println("DemoB--->进去DemoB中的funB(DemoA da)方法!!!!!");
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
da.fun2();
}
public synchronized void fun2(){
System.out.println("DemoB--->进去DemoB中的void fun2()方法!!!!!");
}
}
class ThreadDead implements Runnable{
private DemoA da=new DemoA();
private DemoB db=new DemoB();
public ThreadDead(){
new Thread(this).start();
da.funA(db);
}
public void run(){
db.funB(da);
}
}
public class ThreadDemo16 {
public static void main(String[] args) {
new ThreadDead();
}
}
按我的理解是应该打印:
DemoA--->进去DemoA中的FunA(DemoB db)方法!!!!!
DemoB--->进去DemoB中的void fun2()方法!!!!!
DemoB--->进去DemoB中的funB(DemoA da)方法!!!!!
DemoA--->进去DemoA中的void fun2()方法!!!!!
实际上打印的内容是:
DemoA--->进去DemoA中的FunA(DemoB db)方法!!!!!
DemoB--->进去DemoB中的funB(DemoA da)方法!!!!!
以下代码出自李兴华多线程第四讲~class DemoA { public synchronized void funA(DemoB db){
System.out.println("DemoA--->进去DemoA中的FunA(DemoB db)方法!!!!!");
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
db.fun2();
}
public synchronized void fun2(){
System.out.println("DemoA--->进去DemoA中的void fun2()方法!!!!!");
}
}class DemoB {
public synchronized void funB(DemoA da){
System.out.println("DemoB--->进去DemoB中的funB(DemoA da)方法!!!!!");
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
da.fun2();
}
public synchronized void fun2(){
System.out.println("DemoB--->进去DemoB中的void fun2()方法!!!!!");
}
}
class ThreadDead implements Runnable{
private DemoA da=new DemoA();
private DemoB db=new DemoB();
public ThreadDead(){
new Thread(this).start();
da.funA(db);
}
public void run(){
db.funB(da);
}
}
public class ThreadDemo16 {
public static void main(String[] args) {
new ThreadDead();
}
}
funA()和funB()又互调,所以就锁了
public ThreadDead(){
new Thread(this).start();
da.funA(db);
}
public void run(){
db.funB(da);
}new Thread(this).start();这一行代码表示构造一个Thread对象并启动线程,但是线程初始化有一定的系统开销(run方法并非立即执行),所以,下面一行代码da.funA(db)将会比run方法中的db.funB(da)先被执行。当前线程在执行da.funA(db)时获得da对象锁;
新线程(通过new Thread构造的线程)执行run方法中的db.funB(da)时获得db对象锁;
当前线程执行到db.fun2()时,新线程仍阻塞在Thread.sleep(100)、db对象锁未释放,当前线程因无法获得db对象锁而发生阻塞;
新线程执行到da.fun2()时,当前线程仍阻塞在db.fun2()、da对象锁未释放,新线程因无法获得da对象锁而发生阻塞;
此时这两个线程互相控制对方所需访问资源的锁,并且都因为得不到锁而阻塞,即产生死锁。
上述实例:main线程先去start了一个ThreadDead线程,但是start以后不会马上去执行它的run方法,main线程先走到了da.funA(db),da此时被锁住,main线程sleep,ThreadDead线程run方法起来了运行db.funB(da),此时db被锁住,此时main恢复运行执行db.fun2(),发现db的锁没有被释放,在此等待获得db锁,而ThreadDead执行到da.fun2()时发现da锁也没有释放,他又想获取这个da的锁,结果也在此等待,故此时产生死锁。
解决方案:由于db.fun2()和da.fun2()不涉及的共享数据冲突的问题,把synchonized去掉即可
参考:http://www.lookhan.com/javase/javase/20110103162113.html