更新对不可变对象线程安全的引用

Update reference to immutable object thread-safe

假设多个线程使用同一个 Configuration 对象,有时会从中读取一个 真正 不可变对象。此外,可以更新对不可变对象的引用。

public class Configuration {
    private ImmutableObject immutableObject;
    private ReentrantReadWriteLock lock;

    private void update() {
        lock.writeLock().lock();
        immutableObject = getNewImmutableObject();
        lock.writeLock().unlock();
    }

    public ImmutableObject getImmutableObject() {
        ImmutableObject newRef;
        lock.readLock().lock();
        newRef = immutableObject;
        lock.readLock().unlock();
        return newRef;
    }
}

这是使 immutableObject 的访问线程安全的好方法吗?我想我什至不需要锁,因为引用的更新是原子的,但我不确定。

I think I don't even need the lock, because the update of the reference is atomic

"Atomic" 意味着没有线程会看到 immutableObject 的值未被其他线程存储,但它不会说 when .

如果没有同步,则无法保证(如果 曾经)线程 B 将在线程 A 调用 update() 后看到新值。严重的是,Java 语言规范不要求线程 A ever 存储的值对线程 B 可见,除非在 "happens before" 之间建立了一些链两个线程。

锁定和解锁 Lock 对象建立了这种关系:线程 A 在解锁锁之前存储到任何共享变量中的任何内容都保证线程 B after[=32] 可以看到=] 线程B 锁了同一个锁。

有多种其他方法可以达到相同的效果。您可以使用 synchronized,或者您可以使用某些 java.utils.concurrent 对象,例如隐式同步某些内容的队列或信号量。

或者,您可以将 immutableObject 声明为 volatile。当线程 B 随后读取同一个 volatile 变量时,线程 A 存储到 volatile 变量中的任何内容都保证对线程 B 可见。