本文介绍了Java易失性变量在读取之前强加一个发生先前的关系吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码看起来像这样:



  class Creature {
private static long numCreated;
public Creature(){
synchronized(Creature.class){
numCreated ++;
}
}
public static long numCreated(){
return numCreated;
}
}



从我的理解, c> numCreated 不同步,如果Thread-A在下午1点创建 Creature ,并且Thread-B读取 numCreated )在下午2点, numCreated()可能返回0或1(即使线程A已经完成初始化对象在1.05pm) 。



所以我添加了同步到 numCreated() :



class Creature {
private static long numCreated;
public Creature(){
synchronized(Creature.class){
numCreated ++;
}
}
public static synchronized long numCreated(){//添加synchronized
return numCreated;
}
}

一切正常,除了我在想,if我将其修改为 Snippet C ,是 numCreated 仍正确同步?



  class Creature {
private static volatile long numCreated; // addvolatile
public Creature(){
synchronized(Creature.class){
numCreated ++;
}
}
public static long numCreated(){// removesynchronized
return numCreated;
}
}

使用它保证一旦Thread-A在下午1:05完成对象创建,Thread-B对 numCreated()的调用肯定会返回 1 ?



class Creature {
    private static long numCreated;
    public Creature() {
        synchronized (Creature.class) {
            numCreated++;
        }
    }
    public static long numCreated() {
        return numCreated;
    }
}

From my understanding, since reading of numCreated is not synchronized, if Thread-A creates a Creature at 1pm, and Thread-B reads numCreated() at 2pm, numCreated() may well have returned either 0 or 1 (even when Thread-A has finished initializing the object at 1.05pm).

So I added synchronized to numCreated():

:

class Creature {
    private static long numCreated;
    public Creature() {
        synchronized (Creature.class) {
            numCreated++;
        }
    }
    public static synchronized long numCreated() { // add "synchronized"
        return numCreated;
    }
}

and all's well, except that I was thinking, if I modify it to Snippet C, is the variable numCreated still synchronized properly?

class Creature {
    private static volatile long numCreated; // add "volatile"
    public Creature() {
        synchronized (Creature.class) {
            numCreated++;
        }
    }
    public static long numCreated() { // remove "synchronized"
        return numCreated;
    }
}

With Snippet C, is it guaranteed that as soon as Thread-A completes object creation at 1:05pm, Thread-B's call to numCreated() is sure to return 1 ?

解决方案

See http://download.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility:

So the answer is yes. The write of the volatile in the constructor happens before the read of the volatile in numCreated(). And since the non-atomic incrementation is still done in a synchronized block, the synchronization is alright (the incrementation is not atomic, but the write of the volatile long is).

这篇关于Java易失性变量在读取之前强加一个发生先前的关系吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 23:16