synchronized错误用法
? ? 翻起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的坑还不少。