请教关于synchronized死锁的问题

悬赏:10 发布时间:2008-08-07 提问人:xqstation (初级程序员)

各位好。那个分类里面,实在是不知道该分到哪。

最近在学习多线程方面的知识,
然后发现以前所想的有些误解。
关于synchronized method:
以前认为定义为synchronized的method的lock是跟着method走的,经过学习发现是跟类的实例的。
如,有一个类,有两个方法,method1和method2,然后创建该类的实例,让两个Thread对该实例引用并分别调用这两个方法,执行的时候这两个方法是同步的,也就是需要其中一个执行完了,才会执行下一个。

以下给出代码,我的问题在最后。

先是Interface
public interface DemoInterface {
	public void method1();
	public void method2();
}


具体实现类
public class DefaultClass implements DemoInterface {
	public synchronized void method1(){
		System.out.println("DefaultClass.method1 begin");
		int o = 0;
		for(int i=0; i<100000000; i++){
			o+=i;
		}
		System.out.println("DefaultClass.method1 end");
	}
	
	public synchronized void method2(){
		System.out.println("* DefaultClass.method2 run");
	}
}


两个Thread,分别执行method1和method2
public class TestThread1 extends Thread {
	DemoInterface dc;
	public TestThread1(DemoInterface dc){
		this.dc = dc;
	}
	public void run(){
		this.dc.method1();
	}
}

public class TestThread2 extends Thread {
	DemoInterface dc;
	public TestThread2(DemoInterface dc){
		this.dc = dc;
	}
	public void run(){
		this.dc.method2();
	}
}


最后是main
public class MainRun {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		DemoInterface dc;
		dc = new DefaultClass();
		TestThread1 t1 = new TestThread1(dc);
		TestThread2 t2 = new TestThread2(dc);
		t1.start();
		t2.start();
	}
}


执行的结果是:
DefaultClass.method1 begin
DefaultClass.method1 end
* DefaultClass.method2 run


如果把method2的synchronized定义去掉那么结果将是:
DefaultClass.method1 begin
* DefaultClass.method2 run
DefaultClass.method1 end



问题:
在有synchronized定义的情况下,method1执行时是lock的,直到执行完成才unlock,然后才能执行method2,
但是我在method1中调用method2为什么不是死锁呢?
应该是method1还没执行完,method2在取得锁的时候取不到才对吧。

哪位可以修改以上程序弄个死锁状态出来么?

采纳的答案

2008-08-07 小疯子 (资深程序员)

1, 你在method1中调用method2时, 因为两个方法都是在当前线程中运行, 也就是在同一个线程中运行, 而当前线程是持有锁的, 所以两个方法都会执行, 不会产生死锁
2, 下面是把你的例子修改了一下:
public class DefaultClass implements DemoInterface {
	
	private Object deadLock = new Object();

	public synchronized void method1() {
		synchronized (deadLock) {
			System.out.println("DefaultClass.method1 begin");
			int o = 0;
			for (int i = 0; i < 100000000; i++) {
				o += i;
			}
			System.out.println("DefaultClass.method1 end");
		}

	}

	public void method2() {
		synchronized (deadLock) {
			method3();
		}		
	}

	public synchronized void method3() {
		System.out.println("* DefaultClass.method2 run");
	}

}

这个代码和下面的代码是等效的:
public class DefaultClass implements DemoInterface {

	private Object deadLock = new Object();

	public void method1() {
		synchronized (this) {
			synchronized (deadLock) {
				System.out.println("DefaultClass.method1 begin");
				int o = 0;
				for (int i = 0; i < 100000000; i++) {
					o += i;
				}
				System.out.println("DefaultClass.method1 end");
			}
		}
	}

	public void method2() {
		synchronized (deadLock) {
			synchronized (this) {
				System.out.println("* DefaultClass.method2 run");
			}
		}
	}
}

我列出这两块代码, 是为了向你说明:
public void method1() {
		synchronized (this) {
			System.out.println("DefaultClass.method1 begin");
			int o = 0;
			for (int i = 0; i < 100000000; i++) {
				o += i;
			}
			System.out.println("DefaultClass.method1 end");
		}
	}

public synchronized void method1() {
		System.out.println("DefaultClass.method1 begin");
		int o = 0;
		for (int i = 0; i < 100000000; i++) {
			o += i;
		}
		System.out.println("DefaultClass.method1 end");
	}
是等效的, 锁的都是当前实例(好像说的太啰嗦了, 哈哈!).
3, 测试时多用几个线程:
public static void main(String[] args) {
		DemoInterface dc;
		dc = new DefaultClass();
		for (int i = 0; i < 100; i++) {
			new TestThread1(dc).start();
			new TestThread2(dc).start();
		}
	}

提问者对于答案的评价:
谢谢。出现死锁了。我自己再看看。

其他回答

你给两个方法都加上synchronized
aidiyuxin (资深程序员) 2008-08-07