线程间不同synchronized方法的调用

    以前在学习java sychronized方法在县城之间的同步时,一直把注意力集中在同一个synchronized方法的同步,也就是说,以前自己只知道当一个对象获得了同步锁,并进入一个synchronized方法(比如a())中时,另一个线程在同一个对象上不能再进入到a()方法中。今天在看wait方法时突然想到,另一个线程在同一个对象上是否可以调用这个对象上的其他synchronized方法呢?下面的代码回答了我的问题:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
* 测试当一个线程获取同步锁进入同步控制方法后,另一个线程是否可以调用同一个
* 对象的另外一个同步控制方法
*
* 结果证明,在一个线程获得某对象的锁,并进入该对象的一个同步方法后,其他线程
* 是无法再调用该对象的任何同步访法的,直到那个线程释放锁

*
*/

class TestSynchronized {
public synchronized void f() {
try {
System.out.println(
"In function f()");
System.out.println(
"In function f(), sleeping");
TimeUnit.SECONDS.sleep(
2);
}
catch (InterruptedException e) {
System.out.println(
"Exiting via f() exception");
}
}

public synchronized void g() {
System.out.println(
"In function g()");
System.out.println(
"In function g(), sleeping");
}

public void k() {
System.out.println(
"In function k");
}
}

class Run1 implements Runnable {
private TestSynchronized test;
public Run1(TestSynchronized test) {
this.test = test;
}

@Override
public void run() {
test.k();
test.f();
}
}

class Run2 implements Runnable {
private TestSynchronized test;
public Run2(TestSynchronized test) {
this.test = test;
}

@Override
public void run() {
test.k();
test.g();
}
}

public class ObjectSynchronized {

public static void main(String[] args) throws Exception{
TestSynchronized test
= new TestSynchronized();
Run1 run1
= new Run1(test);
Run2 run2
= new Run2(test);
ExecutorService exec
= Executors.newCachedThreadPool();

exec.execute(run1);
exec.execute(run2);

exec.shutdown();
}

}

运行这个程序的结果如下:

In function k
In function f()
In function k
In function f(), sleeping
In function g()
In function g(), sleeping

    这说明,当一个线程A的某个对象获取锁进入一个同步方法之后,另一个线程B的同一个对象就不能再调用这个对象上的任何synchronized方法,直到线程A的那个对象释放锁。

    这也就是为什么wait()在调用时要释放对象已获取的锁的原因:如果线程A因为等待某个条件而调用wait(),如果它不释放已经获得的同步锁,那么其他线程可能就无法改变这个对象当中的某些条件(因为无法再进入这个对象的同步方法中),导致死锁的发生。

posted on 2011-04-16 15:43  Kadin Zhu  阅读(876)  评论(7编辑  收藏  举报