线程间不同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(),如果它不释放已经获得的同步锁,那么其他线程可能就无法改变这个对象当中的某些条件(因为无法再进入这个对象的同步方法中),导致死锁的发生。