3

我知道构造函数不能在Java中同步。这是否意味着,如果构造函数修改类中的静态变量,并且可以从多个线程调用构造函数,那么访问需要同步,如图所示?在构造函数中访问共享静态变量是否需要同步?

public class MyClass { 
    private static int count = 0; 

    public MyClass() { 
    synchronized(MyClass.class) { 
     count++; 
    } 
    ... 
    } 
} 
+2

你知道静态的,可变的变量是代码味道,对吗? – 2012-03-01 19:58:29

+0

@LouisWasserman,我没有意识到他们被认为是一种气味,但我现在就做。谢谢。 – 2012-03-01 20:06:41

+1

[这里](http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial)是一个可能解释_why_他们是代码味道的引用。它着重于单例 - 这是静态的一个特例 - 但这个问题更普遍适用。 – 2012-03-01 20:23:37

回答

8

绝对 - 毕竟,它的访问共享资源,可能通过多线程。我个人只是使​​用AtomicInteger来代替。

public class MyClass { 
    private static final AtomicInteger count = new AtomicInteger(); 

    public MyClass() { 
    count.incrementAndGet(); 
    } 
} 

注意,我们现在可以把这些变量最终为变量不改变价值,我们并不需要同步任何更多的为java.util.concurrent.atomic类的整点是,他们可以无需额外的同步就可以自动使用。

即使你是在您需要同步的情况下,我不会用MyClass.class这样做 - 这就是它的其他代码可能会决定要同步的一个参考,所以你不能真正原因有关代码更多。我会写(同样,只AtomicInteger是不是出于某种原因不够好):

public class MyClass { 
    private static final Object countLock = new Object(); 
    private static int count = 0; 

    public MyClass() { 
    synchronized(countLock) { 
     count++; 
    } 
    ... 
    } 
} 

(在这种情况下,你想也想在countLock其他地方同步访问count,甚至只是为了读书。 )

+0

+1非常好,非常完整的答案。 – 2012-03-01 20:12:11

+0

据推测'count'正在其他地方使用。在第二个示例中,您还希望在'countLock'上同步任何对'count'的读取访问。 – 2012-03-01 20:52:17

+0

@TedHopp:的确如此。将这样编辑。 – 2012-03-01 20:55:48

1

某种形式的同步是必要的,这是行得通的,是的。它将完成与同步静态方法相同的功能。您可以考虑改用AtomicInteger

1

对于这种情况,我建议你使用AtomicInteger

+0

我觉得有必要投入这个词:“要被激怒!” – Gray 2012-03-01 20:19:12

+0

@格雷 - 的确如此。但必须在信贷到期时给予贷款。这是一个很好的答案。 – 2012-03-01 20:49:09

+0

当然可以。这就是他为什么是John Skeet的原因。 – Gray 2012-03-01 20:51:34