问题
Small question about memory visibility.
CodeSample1:
class CustomLock {
private boolean locked = false;
public boolean lock() {
if(!locked) {
locked = true;
return true;
}
return false;
}
}
This code is prone to bugs in a multi-threaded environment, first because of the "if-then-act" which is not atomic, and second because of potential memory visibility issues where for example threadA sets the field to true, but threadB that later wishes to read the field's value might not see that, and still see the value false.
The simplest solution is to use the synchronized keyword, as in CodeSample2.
CodeSample2:
class CustomLock {
private boolean locked = false;
public synchronized boolean lock() {
if(!locked) {
locked = true;
return true;
}
return false;
}
}
Now what if I wish to use an atomic variable, and for the example, an AtomicBoolean (question applies to all atomic variables),
CodeSample3:
public static class CustomLock {
private AtomicBoolean locked = new AtomicBoolean(false);
public boolean lock() {
return locked.compareAndSet(false, true);
}
}
Better performance considerations aside, we can see that now we've implemented similar logic to the "if-then-act" from CodeSample1, using AtomicBoolean. It doesn't really matter what the code does logically, the question I have is what if 2 threads invoke the lock() method in CodeSample3 right about the same time, while it's clear that any write operation to the field will now be done atomically, does the use of AtomicBoolean also guarantees memory visibility?
Sorry for the long story, just wanted to make sure I'm coming across as clear as possible, Thanks guys...
回答1:
Yes, according to the javadocs it guarantees:
compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
回答2:
the question I have is what if 2 threads invoke the lock() method in CodeSample3 right about the same time, while it's clear that any write operation to the field will now be done atomically, does the use of AtomicBoolean also guarantees memory visibility?
For AtomicBoolean
to handle multiple operations from different threads at the same time it has to guarantee memory visibility. It can make the guarantee because it wraps a volatile
field. It is the language semantics of the volatile
which ensures that memory barriers are crossed so that multiple threads see the most up to date value and that any updates will be published to main memory.
Btw, your lock(...)
method should ready be tryLock(...)
because it might not get the lock.
来源:https://stackoverflow.com/questions/42868163/does-atomic-variables-guarantee-memory-visibility