As an example, if I have:

(def a (atom 5))

and execute these from different threads:

T1: (swap! a * 2)
T2: (swap! a + 2)

it depends on timing which update runs first so you can get either 12 (T1 
then T2) or 14 (T2 then T1). But it must be one of those results.

With a volatile, the reads and writes can interleave in a variety of ways 
(I think this is all of them as the JMM will guarantee that the read 
happens-before the write for each T):

T1 read, T1 write, T2 read, T2 write: v = 12
T1 read, T2 read, T1 write, T2 write: v = 7  (T1 write is effectively lost)
T1 read, T2 read, T2 write, T1 write: v = 10 (T2 write is effectively lost)
T2 read, T2 write, T1 read, T1 write: v = 14
T2 read, T1 read, T2 write, T1 write: v = 10 (T2 write is effectively lost)
T2 read, T1 read, T1 write, T2 write: v = 7  (T1 write is effectively lost)

Non-atomic updates are fine if you have thread isolation though, as there 
is no chance for interleaving as above. The atomicity you get from atoms 
must be provided as a consequence of program construction in that case. 
There are a very small set of cases where non-atomic multi-threaded updates 
as above are actually valid. [The racy single-check idiom used for hash 
caching is one - that's a special case where the update function and 
initial value are identical so threads race to produce the *same* value, 
and all interleavings produce the same result. This technique used in 
several places in Clojure for hash caching.]

Also note that the default in Java (non-volatile, non-synchronized fields) 
is even worse than this - they provide neither visibility nor atomicity, so 
different threads may not even seen writes by other threads at all (not to 
mention things like long-tearing).


On Wednesday, September 10, 2014 9:19:33 AM UTC-5, Alex Miller wrote:
>
> Usually that's called "visibility". 
>
> Atoms are *not* subject to race conditions if swap! is called from 
> multiple threads (the state of the atom will not change while the update 
> function is being applied). The atom is thus "safe" to be used from 
> multiple threads.
>
> Volatiles *are* subject to race conditions with vswap! is called from 
> multiple threads (the state of the volatile may change while the update 
> function is being applied). The volatile is thus "dangerous" and safety is 
> derived from how it's used.
>
> On Wednesday, September 10, 2014 8:44:27 AM UTC-5, Brent Millare wrote:
>>
>> When I say synchronization, I specifically mean "writes are guaranteed to 
>> be seen by subsequent reads on any thread*" *as Alex said.
>>
>> On Wednesday, September 10, 2014 9:37:09 AM UTC-4, Brent Millare wrote:
>>>
>>> So to summarize, Clojure's volatile provides synchronization across 
>>> threads but does not provide atomaticity with vswap!. So, as a follow up 
>>> question, then why would the creation of a volatile be "dangerous" but 
>>> creating an atom isn't? (Hence the exclamation point in the name 
>>> "volatile!")
>>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to