双重检查锁定是否仅在惰性初始化场景中被破坏?
Is double-checked locking only broken in a lazy initialization scene?
我读了这篇文章:The "Double-Checked Locking is Broken" Declaration,它说
Double-Checked Locking is widely cited and used as an efficient method
for implementing lazy initialization in a multithreaded environment.
Unfortunately, it will not work reliably in a platform independent way
when implemented in Java...
而这篇文章:Double-checked locking: Clever, but broken,它说:
The DCL idiom was designed to support lazy initialization...
我的问题是:
双重检查锁定是否仅在尝试进行惰性初始化时被破坏?
是不是像下面代码这样的场景也坏掉了(所有的东西都已经初始化好了)?
代码:
public String refreshJsapiTicket() throws WxErrorException {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
synchronized (wxMpConfigStorage) {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
// ...
// update
wxMpConfigStorage.setJsapiTicket(jsapiTicket, expiresInSeconds);
}
}
}
}
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected volatile String jsapiTicket;
protected volatile long jsapiTicketExpiresTime;
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
this.jsapiTicket = jsapiTicket;
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
}
}
第 1 个答案:是的。 From Java 5 class 加载器保证静态字段的单次或一次性初始化。
对您的 2 的回答:从代码中看不清楚,但这取决于您在 wxMpConfigStorage.isJsapiTicketExpired() 方法中阅读的内容。如果您决定基于阅读非线程安全的内容,那么是的,DCL 可能会失败。但在您的情况下,jsapiTicketExpiresTime 是易变的,因此线程可以安全读取,因此 DCL 将为您工作。
我读了这篇文章:The "Double-Checked Locking is Broken" Declaration,它说
Double-Checked Locking is widely cited and used as an efficient method for implementing lazy initialization in a multithreaded environment.
Unfortunately, it will not work reliably in a platform independent way when implemented in Java...
而这篇文章:Double-checked locking: Clever, but broken,它说:
The DCL idiom was designed to support lazy initialization...
我的问题是:
双重检查锁定是否仅在尝试进行惰性初始化时被破坏?
是不是像下面代码这样的场景也坏掉了(所有的东西都已经初始化好了)?
代码:
public String refreshJsapiTicket() throws WxErrorException {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
synchronized (wxMpConfigStorage) {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
// ...
// update
wxMpConfigStorage.setJsapiTicket(jsapiTicket, expiresInSeconds);
}
}
}
}
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected volatile String jsapiTicket;
protected volatile long jsapiTicketExpiresTime;
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
this.jsapiTicket = jsapiTicket;
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
}
}
第 1 个答案:是的。 From Java 5 class 加载器保证静态字段的单次或一次性初始化。 对您的 2 的回答:从代码中看不清楚,但这取决于您在 wxMpConfigStorage.isJsapiTicketExpired() 方法中阅读的内容。如果您决定基于阅读非线程安全的内容,那么是的,DCL 可能会失败。但在您的情况下,jsapiTicketExpiresTime 是易变的,因此线程可以安全读取,因此 DCL 将为您工作。