Synchronize write access to Volatile field (Cheap read-write block)

时间秒杀一切 提交于 2019-11-30 19:12:05
Evgeniy Dorofeev

Volatile provides fast thread-safe lock-free access to a field without synchronization

private volatile String foo;

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

volatile solves 3 problems 1) memory visibility 2) atomic writes for double and long fields 3) forbids instructions reordering. But it's not enough if you need several operations over a field as one atomic transaction, such as increment. This code is broken

private volatile int id;

public void incrementId() {
     id++;
}

because if 2 threads simulataneously read and increment it and save the result then the result of the first increment will be overwritten with the result of the second increment. To prevent this from happening we need to use synchronization

 private int id;

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

or java.util.concurrent.atomic package

 private AtomicInteger id = new AtomicInteger();

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

If all you are doing is setting foo, then you don't need to synchronize the method. making the reference volatile is sufficient.

At the link you said there is this code for "infrequent updates" usage:

@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++;
    }
}

The increment method is only using synchronized because it is doing more than just setting the value of value as stated in the description, if all you are doing is this.foo = in; that is atomic. In the text the "fragility of this pattern" means things can get messy very fast when you mix volatile and other synchronization methods to do more than just simple examples. See package java.util.concurrent.locks for the interfaces Condition and Lock and the class ReentrantLock. I think that, and using synchronized is what the author means by "stronger alternatives". You should also see Object.wait, Object.notify and Object.notifyAll if you don't know that yet.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!