Java – volatile references to mutable objects – updates to the object’s fields are visible to all threads

... no additional synchronization? The following tree class is intended to be accessed by multiple threads (it is a singleton, but not through enumeration)

class Tree {

    private volatile Node root;

    Tree() {
        root = new Node();
        // the threads are spawned _after_ the tree is constructed
    }

    private final class Node {
        short numOfKeys;
    }
}

>The reader thread's updates to the numofkeys field are visible without any explicit synchronization (note that readers and writers must obtain an instance of reentrantreadwritelock - the same instance for each node - but otherwise)? If not, will numofkeys volatile be sufficient? > Change root to root = new node() (only one write thread can change the root, except the main thread calling the tree constructor)

of

> multiple fields: volatile or AtomicReference? > Is volatile enough for changing reference to a list? > Are mutable fields in a POJO object threadsafe if stored in a concurrentHashMap? > Using volatile keyword with mutable object

Editor: interested in publishing Java 5 semantics

Solution

These two questions Let's start with the second one

Assigning newly constructed objects to variables works well Every thread reading volatile variables will see a fully constructed object No further synchronization is required This pattern is usually used in conjunction with immutable types

class Tree {
    private volatile Node node;
    public void update() {
        node = new Node(...);
    }
    public Node get() {
        return node;
    }
}

On the first question, you can use volatile variables to synchronize access to nonvolatile variables The following list shows an example Suppose two variables are initialized, as shown in the figure, and the two methods are executed concurrently This is guaranteed. If the second thread sees the update to foo, it will also see the update bar

volatile int foo = 0;
int bar = 0;

void thread1() {
    bar = 1;
    foo = 1; // write to volatile variable
}

void thread2() {
    if (foo == 1) { // read from volatile variable
        int r = bar; // r == 1
    }
}

But your example is different Reading and writing may be as follows Contrary to the above example, both threads read from the volatile variable However, reads to volatile variables are not synchronized with each other

void thread1() {
    Node temp = root; // read from volatile variable
    temp.numOfKeys = 1;
}

void thread2() {
    Node temp = root; // read from volatile variable
    int r = temp.numOfKeys;
}

In other words, if thread a writes volatile variable x and thread B reads the value of write x, thread B will see all write operations of thread a before writing X after the read operation However, there is no write operation on volatile variables, and it has no impact on the update of other variables

It sounds more complicated than it really is In fact, there is only one rule to consider, which you can see in jls8 § 17.4 5 find:

In short, if two threads can access the same variable at the same time, there is data competition. At least one operation is a write operation, and the variable is nonvolatile You can eliminate data races by declaring shared variables volatile There is no data competition, and there is no problem with the visibility of updates

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>