Class Future
{
private volatile boolean ready;
private Object data;
public Object get()
{
if(!ready) return null;
return data;
}
public synchronized void setOnce(Object o)
{
if(ready) throw...;
data = o;
ready = true;
}
}
It said "if a thread reads data, there is a happens-before edge from write to read of that guarantees visibility of data"
I know from my learning:
- volatile ensures that every read/write will be in the memory instead of only in cache or registers;
- volatile ensures reorder: that is, in setOnce() method data = o can only be scheduled after if(ready) throw..., and before ready = true; this guarantee that if in get() ready = true, data must be o.
My confusion is
is it possible that when thread 1 is in setOnce(), reaches the point that after data = o; before ready = true; At the same time, thread 2 runs into get(), read ready is false, and return null. And thead 1 continues ready = true. In this scenario, Thread 2 didn't see the new "data" even though data has been assigned new value in thread 1.
get() isn't synchronized, that means the synchronized lock cannot protect setOnce() since thread 1 calls get() that needn't acquire the lock to access variable ready, data. So thread are not guaranteed to see the latest value of data. By this, I mean lock only guarantee the visibility between synchronized blocks. Even though one thread is running synchronized block setOnce(), another thread is still can go into get() and access ready and data without blocking and may see the old value of these variables.
in get(), if ready = true, data must be o? I mean this thread is guaranteed to see the visibility of data? I think data is not a volatile nor the get() synchronized. Is this thread may see the old value in the cache?
Thanks!
1
is mostly false. Thevolatile
keyword has to do with memory visibility, not caches. Caches are handled by cache coherency hardware. And that would be an obviously awful design that nobody would use -- memory is way too slow to use that way. – Iorgovolatile
keyword has nothing whatsoever to do with these caches. Access to avolatile
can remain entirely in an L1 cache with no issues. (Sadly, the article that you linked to repeats the myth.) – Iorgovolatile
disables), nothing to do with CPU caches. (This really is something that very, very few people actually understand.) – Iorgovolatile
. Some CPUs do have prefetch buffers or write posting buffers that do hide things from other processors, andvolatile
does have to work around those. – Iorgo