Reading this DZone article about Java concurrency I was wondering if the following code:
private volatile List list;
private final Lock lock = new ReentrantLock();
public void update(List newList) {
ImmutableList l = new ImmutableList().addAll(newList);
lock.lock();
list = l;
lock.unlock();
}
public List get() {
return list;
}
is equivalent to:
private volatile List list;
public void update(List newList) {
ImmutableList l = new ImmutableList().addAll(newList);
list = l;
}
public List get() {
return list;
}
The try { } finally { } block was omitted for brevity. I assume the ImmutableList class to be a truly immutable data structure that holds its own data, such as the one provided in the google-collections library. Since the list variable is volatile and basically what's going on is a copy-on-the-fly, isn't it safe to just skip on using locks?
In this very specific example, I think you would be OK with no locking on the variable reassignment.
In general, I think you are better off using an AtomicReference instead of a volatile variable as the memory consistency effects are the same and the intent is much clearer.
Yes, both of those code samples behave the same way in a concurrent environment. Volatile fields are never cached thread-locally, so after one thread calls update(), which replaces the list with a new list, then get() on all other threads will return the new list.
But if you have code which uses it like this:
list = get()
list = list.add(something) // returns a new immutable list with the new content
update(list)
then it won't work as expected on either of those code examples (if two threads do that in parallel, then the changes made by one of them may be overwritten by the other). But if only one thread is updating the list, or the new value does not depend on the old value, then no problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With