java 同步锁静态方法_java – 静态初始化器和静态同步方法锁定问题

我在我的应用程序中遇到了一些锁定问题,其中包含几个类,如下所示:

public interface AppClient {

void hello();

}

public class Client implements AppClient {

public synchronized static AppClient getInstance() {

return instance;

}

public void hello() {

System.out.println("Hello Client");

}

private final static class InnerClient implements AppClient {

public void hello() {

System.out.println("Hello InnerClient");

}

}

private static AppClient instance;

static {

instance = new InnerClient();

doSomethingThatWillCallClientGetInstanceSeveralTimes();

}

}

public class Application {

new Thread() {

AppClient c = Client.getInstance();

c.hello();

}.start();

new Thread() {

AppClient c = Client.getInstance();

c.hello();

}.start();

// ...

new Thread() {

AppClient c = Client.getInstance();

c.hello();

}.start();

}

在doSomethingThatWillCallClientGetInstanceSeveralTimes()方法中,它会做很多涉及很多类的初始化工作,并在初始化期间多次循环调用Client.getInstance静态方法(我明白这不好,但是,这是一个持久的遗留代码库20年).

这是我的问题:

1)我想在类客户端初始化完成之前,只有触发类Client初始化的第一个线程可以访问Client.getInstance方法,因为JVM将在类初始化完成之前在Client.class对象上同步.我阅读了相关主题的JLS并得出了这个结论(第12.4.2节,详细初始化过程,http://java.sun.com/docs/books/jls/third_edition/html/execution.html).

2)但是,这不是我在真实环境中看到的行为.例如,有三个线程调用Client.getInstance(),thread-1触发Client.class初始化,并多次调用doSomethingThatWillCallClientGetInstanceSeveralTimes()方法中的Client.getInstance().在doSomethingThatWillCallClientGetInstanceSeveralTimes()方法完成之前,thread-2获取了Client.class对象的锁(这怎么可能?但它确实发生了),并进入Client.getInstance方法(因为这个方法是一个静态同步方法) .由于某种原因,thread-2无法返回“实例”(我猜它正在等待Client.class完成其初始化).同时,thread-1无法继续,因为它仍然需要在doSomethingThatWillCallClientGetInstanceSeveralTimes()中调用Client.getInstance并且由于它由thread-2拥有而无法获取锁. Threaddump告诉我thread-2处于RUNNABLE状态,而thread-1处于BLOCKED状态,等待thread-2拥有的锁.

我只能在Windows中的64位Java 6u23 JVM中重现此行为,并且无法在32位Java 6 JVM Windows环境中重现它.谁能告诉我在这里我错过了什么?这种代码注定会引起这样的锁定,如果是的话,怎么来的?我对JLS这部分的理解是不正确的?或者它是JVM问题?任何帮助表示赞赏.谢谢.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值