翻起tomcat5的源码,看到standardServer.java中的addservice方法:
public void addService(Service service) {
service.setServer(this);
synchronized (services) {
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results; ---此处会导致同步失效,因为改写了锁的对象,也就是锁指向的区域发生了改变
if (initialized) {
try {
service.initialize();
} catch (LifecycleException e) {
e.printStackTrace(System.err);
}
}
if (started && (service instanceof Lifecycle)) {
try {
((Lifecycle) service).start();
} catch (LifecycleException e) {
;
}
}
// Report this property change to interested listeners
support.firePropertyChange("service", null, service);
}
}
由于Thread.Sleep()不会失去拥有的对象锁,做个例子验证一下
public class Test {
private static Object lock = new Object();
public static void main(String[] args) {
new Thread(){
public void run() {
synchronized (lock) {
System.out.println("thread1-----enter");
lock = new Object() ; //更换锁的对象
try {
Thread.sleep(3000); //让线程2可以运行,看是否能进入代码块
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1-----exit");
}
}
}.start();
new Thread(){
public void run() {
try {
Thread.sleep(1000);//让上面的线程1先进入同步代码块
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
System.out.println("thread2-----enter");
System.out.println("thread2-----exit");
}
}
}.start();
}
}
输出的结果为
thread1-----enter
thread2-----enter
thread2-----exit
thread1-----exit
可见上面的同步失败,连写tomcat的大牛都出错,synchronized的坑真不小。