Java多线程getter和setter

时间:2014-07-16 11:52:09

标签: java multithreading static volatile

假设我有一个实例变量,我有setter和getters。

代码1:

Class<T> {
    volatile T value;

    public synchronized void set(T v) {
        if(value==null) {
            value=v;
        }

    }

    public T get() {
        return value;
    }
} 

代码2:

Class<T> {
    static volatile T value;

    public synchronized void set(T v) {
        if(value==null) {
            value=v;
        }
    }

    public T get() {
        return value;
    }
}

我有两个问题

1)静态易失性状态字段和仅易失性状态字段有什么区别?

2)我刚刚了解了易失性读/写的发布/获取概念,并了解到没有必要同步getter(因为缓存刷新)。但是有没有需要同步setter?

2 个答案:

答案 0 :(得分:0)

让我们从你的第二个问题开始:

我认为您在设置器中使用同步块的原因是您在value上执行两个不同的操作。您检查value==null,然后设置value=v。虽然您在每个步骤中都有锁定,但它们之间没有锁定。所以这是可能的:

Thread1: lock value -> value==null (true) -> release value
Thread2: lock value -> value==null (true) -> release value
Thread1: lock value -> value=v -> release value;
Thread2: lock value -> value=v -> release value;

所以你仍然有竞争条件。

现在回到你的第一个问题:你应该使用static来让你的类的任何实例使用相同的变量T而不是拥有自己的变量。

答案 1 :(得分:-2)

在代码2中,可能存在以下情况:

Thread1: calls set(X) on instance1
Thread1: value is null, entering inside if
Thread2: calls set(Y) on onstance2
Thread2: value is null, entering inside if
Thread2: setting value = Y
Thread1: setting value = X

问题是在类的实例上获取了锁,而不是类本身。如果您要将setget方法更改为static,那么它会再次正常工作。