Java:如何使用数组元素进行双重检查锁定?
这就是我的代码当前的样子:Java:如何使用数组元素进行双重检查锁定?,java,multithreading,arrays,synchronized,double-checked-locking,Java,Multithreading,Arrays,Synchronized,Double Checked Locking,这就是我的代码当前的样子: private boolean[] isInitialized = new boolean[COUNT]; private void ensureInitialized(int i) { if (! isInitialized[i]) { initialize(i); isInitialized[i] = true; } } 现在我想让它线程安全。我知道Java中的双重检查锁定是非常卑鄙的!!1,但由于经常调用ens
private boolean[] isInitialized = new boolean[COUNT];
private void ensureInitialized(int i) {
if (! isInitialized[i]) {
initialize(i);
isInitialized[i] = true;
}
}
现在我想让它线程安全。我知道Java中的双重检查锁定是非常卑鄙的!!1,但由于经常调用ensureInitialized,我不希望它被同步。所以我想这样做:
private boolean[] isInitialized = new boolean[COUNT];
private void ensureInitialized(int i) {
if (! isInitialized[i]) {
synchronized (this) {
if (! isInitialized[i]) {
initialize(i);
isInitialized[i] = true;
}
}
}
}
现在我该怎么做才能保证线程安全呢?
一些子问题:
没有必要使isInitialized为volatile,因为变量没有改变,对吗?
数组元素已更改,如何使其易变?
有没有更好的方法?
还请注意,这是一个实例方法,因此静态初始值设定项将不起作用。请注意,双重检查的java实现被称为断开模式,因为它被证明是失败的,例如,请参阅。要解决这个问题,只需使用原子操作。下面是如何构建线程安全单例的示例:
static AtomicReferenceArray<Boolean> instance =
new AtomicReferenceArray<Boolean>(COUNT);
private void ensure(int i)
{
if(!instance.get(i) )
{
synchronized(this){
if( !instance.get(i) ){
initialize(i);
instance.set(i, true);
}
}
}
请注意,双重检查的java实现被称为断开模式,因为它被证明是失败的,例如,请参阅。要解决这个问题,只需使用原子操作。下面是如何构建线程安全单例的示例:
static AtomicReferenceArray<Boolean> instance =
new AtomicReferenceArray<Boolean>(COUNT);
private void ensure(int i)
{
if(!instance.get(i) )
{
synchronized(this){
if( !instance.get(i) ){
initialize(i);
instance.set(i, true);
}
}
}
您也可以考虑使用.P/IOMIZUPPLILE委托从.< /P> < P>您也可以考虑使用.PoiiSeri.MeoIZEPSUpPLER从./P>有证据表明java的同步是否不必要地慢?换句话说,是的,当有争用时它是慢的,但是当没有争用时它是快的。+1,但是一个解释是应该的。双重检查锁没有被打破,因为Java1.5使用volatile关键字使其工作正常。然而,正如OP正确地假设的那样,对数组元素的读写不是易变的。AtomicXArray类所做的是对每个元素执行volatile读取,查看源代码-unsafe.getObjectVolatile.-1,双重检查锁定是否被破坏。其余答案在技术上是正确的。“也许少一点说教,多一些技术解决方案?”蒂姆·本德(Tim Bender)——只需访问链接和/或阅读@Bozho的评论。或者至少试着用谷歌搜索一下“java双重检查”这个短语pattern@GregS-这很有趣,如果没有争用,为什么我们要使用同步呢?当您确定单线程延迟加载模式只使用单线程时,是否有证据表明java的同步速度太慢了?换句话说,是的,当有争用时它是慢的,但是当没有争用时它是快的。+1,但是一个解释是应该的。双重检查锁没有被打破,因为Java1.5使用volatile关键字使其工作正常。然而,正如OP正确地假设的那样,对数组元素的读写不是易变的。AtomicXArray类所做的是对每个元素执行volatile读取,查看源代码-unsafe.getObjectVolatile.-1,双重检查锁定是否被破坏。其余答案在技术上是正确的。“也许少一点说教,多一些技术解决方案?”蒂姆·本德(Tim Bender)——只需访问链接和/或阅读@Bozho的评论。或者至少试着用谷歌搜索一下“java双重检查”这个短语pattern@GregS-这很有趣,如果没有争用,为什么我们要使用同步呢?当你确信单线程惰性加载模式只使用单线程就足够了,我喜欢这样的回答:双重检查锁定真是太糟糕了!我不想在我的代码中看到任何内容:我支持它。在我找到这个成语后,我再也没有回头。这个习惯用法的优点是,图书馆的工作人员总是试图找到最好的方法,如果他们找到了更好的方法,他们会改变它,而你不必在代码库中重写上千个双重检查块。我喜欢这样的回答:双重检查锁定真是太可怕了!我不想在我的代码中看到任何内容:我支持它。在我找到这个成语后,我再也没有回头。这个习惯用法的优点是,库人员总是会尝试使用最好的方法,如果他们找到了更好的方法,他们会改变它,而您不必在代码库中重写上千个重复检查的块。