同步到挥发性场的写权限(便宜读写块)(Synchronize write access to Vol

2019-07-20 23:58发布

比方说,我有一个会被大量阅读,但只写了偶尔下面的类。 它会在一个多线程的web应用程序中使用,所以它需要是线程安全的:

public class Foo {
    private volatile String foo;
    public String getFoo() {
        return foo;
    }
    public synchronized String setFoo(String in) {
        this.foo = in;
    }
}

Java并发( http://www.ibm.com/developerworks/java/library/j-jtp06197/index.html )指出,这是为了保护写访问,同时提高读取访问一个脆弱的方式。 什么是这种模式更强的选择吗? 或者有什么选择,如果foo将需要可变在读重的环境? 谢谢。

Answer 1:

挥发性提供不同步的现场快速线程安全的无锁访问

private volatile String foo;

public String getFoo() {
    return foo;
}
public void setFoo(String in) {
    this.foo = in;
}

易失性解决了问题3 1)存储器能见度2)原子写入双和长字段3)禁止指令重新排序。 但是,这还不够,如果你需要在一个领域的一些经营为一体的原子事务,如增量。 这段代码被打破

private volatile int id;

public void incrementId() {
     id++;
}

因为如果2个线程simulataneously阅读并增加它并保存结果,那么第一个增量的结果将与第二增量的结果覆盖。 为了防止这种情况发生,我们需要使用同步

 private int id;

 public synchronized int nextId() {
       return ++id;
 }

或java.util.concurrent.atomic包

 private AtomicInteger id = new AtomicInteger();

 public void incrementId() {
     return id.incrementAndGet();
 }


Answer 2:

如果你正在做的是设置FOO,那么你并不需要同步的方法。 使参考挥发性是足够的。



Answer 3:

在链接你说有此代码为“罕见的更新”的用法:

@ThreadSafe
public class CheesyCounter {
    // Employs the cheap read-write lock trick
    // All mutative operations MUST be done with the 'this' lock held
    @GuardedBy("this") private volatile int value;

    public int getValue() { return value; }

    public synchronized int increment() {
        return value++;
    }
}

increment方法只使用同步的,因为它所做的不仅仅是设定的值更value如说明书中所述,如果你正在做的是this.foo = in; 这是原子。 在文本中“这种模式的脆弱性”是指当你混合的挥发性和其他同步方法做的不仅仅是简单的例子更多的东西会导致混乱非常快。 请参阅接口的条件锁定和类ReentrantLock的包java.util.concurrent.locks中。 我认为,用同步是笔者指“更强的替代品”的东西。 你也应该看到Object.wait,Object.notifyObject.notifyAll,如果你不知道呢。



文章来源: Synchronize write access to Volatile field (Cheap read-write block)