The simple inaccurate answer is after every write they are written to main memory.
The real answer is ...
volatile doesn't guarantee to write to main memory at all , it doesn't have to and actually guarantees a lot more.
Strictly volatile guarantees that a volatile write will "happen before" any subsequent volatile read and this covers a wide range of possible issues of which caching is one.
First ...
I know thread will keep the local copy for some time
it may (appear) to keep it forever or not at all, there is a tendency to think of volatiles resulting in mem barrier /
fence like instructions but its not always the case and this is a gross simplification.
A write to main memory is considered expensive so the JVM is free to perform any optimisation to prevent it as long as it maintains the rules of the
Java memory model.
If the JVM can guarantee the write can never be observed by another thread it doesn't have to publish it, volatile in theory can be free.
CPU's don't have to communicate via main memory they can also in some cases look into or invalidate each others caches , if the JVM knows that cache snooping would guarantee the java memory model (effectively the memory ordering guarantees of the processor) it wouldn't force a main memory write. CPU's publish nice tables of how stores and loads can be reordered or not.
volatile also potentially removes some compiler / JVM optimisations as necessary whose effect might appear as caching ..
... in this case it will appear as if done is cached infinitely, volatile prevents this optimisation also Terracotta for instance can use I believe a volatile write to maintain memory consistency across remote JVM's i.e your volatile write causes an IP communication in that case.
So the best answer is forget about how it does it and only in terms what it guarantees .
If you need a better or more formal answer please read this ...
Java memory model
or post here ...
javamemorymodel-discussion@cs.umd.edu