类定义:
public class Test{
public synchronized method1(){...}
public synchronized method2(){...}
}
问题:
多线程并发访问method1和method2时,两者会互斥吗?
下面的测试程序来回答这个问题。
public class TestSynchronizedMethod {
private void ivkMethod1(){
Thread thread1 = new Thread() {
public void run() {
for(int i = 0; i < 20; i++) {
//System.out.println("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//System.out.println("~~~~ start thread method1 ");
method1();
//System.out.println("~~~~ end thread method1 ");
}
}
};
thread1.start();
}
private void ivkMethod2(){
Thread thread2 = new Thread() {
public void run() {
for(int i = 0; i < 20; i++) {
//System.out.println("\n\n#################################################");
//System.out.println("#### start thread method2 ");
method2();
//System.out.println("#### end thread method2 ");
}
}
};
thread2.start();
}
private synchronized void method1(){
System.out.println("\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("~~~~ enter method1");
try{
System.out.println("~~~~ method1 begin to sleep 10s");
Thread.sleep(10000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("~~~~ method1 end sleep");
}
private synchronized void method2(){
System.out.println("\n\n#################################################");
System.out.println("#### enter method2");
try{
System.out.println("#### method2 begin to sleep 3s");
Thread.sleep(3000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("#### method2 end sleep");
}
/**
* @param args
*/
public static void main(String[] args) {
try {
TestSynchronizedMethod obj = new TestSynchronizedMethod();
obj.ivkMethod1();
obj.ivkMethod2();
} catch (Exception e) {
e.printStackTrace();
} catch (Error er) {
er.printStackTrace();
}
}
}
结论很明显,无需多言。究其原因,method1和method2所持的锁为obj实例锁,所以当对同一obj调用两个方法时,两者不能并发执行。编码时要注意这一点,这种情况下对象的并发能力比较差,可参考下java.util.Vector的get和set方法,就很容易理解为什么JDK新版本中提供了替代的List接口了。