>
> Hi all,
>
> I'm enjoying using Clojure. It is clean, concise and powerful.
>
> The containers and even defmacro are easy to use correctly. However,
> I'm yet to be convinced the same applies with the STM implementation.
>
> In the user code below, people might expect b == a + 1 after the two
> transactions run. Unfortunately, that isn't the case, as no read locks
> are being taken. (It would have been true if the transactions ran
> sequentially, in either order.)
>
> Is the lack of isolation affecting people, or do most users use idioms
> that avoid the problem?
> Example idioms would be writing every ref that is read, or using a
> single ref to switch to a new immutable data structure (as opposed to
> implementing mutable data structures using numerous refs).
>
> Regards,
> Eric.
>
> P.S. I'm aware Oracle and PostgreSQL similarly have non-serializable
> transactions.
>
It's not a lack of isolation. It is snapshot isolation, and is subject
to write-skew.
http://en.wikipedia.org/wiki/Snapshot_isolation
As documented here:
point #8:
"If a constraint on the validity of a value of a Ref that is being
changed depends upon the simultaneous value of a Ref that is not being
changed, that second Ref can be protected from modification by calling
ensure. Refs 'ensured' this way will be protected (item #3), but don't
change the world (item #2)."
That describes your situation, and you can use 'ensure' to ensure the
serializability of your reads. This is better than the "dummy write"
solution in that multiple ensures of the same refs don't conflict.
You should be able to use ensure to avoid write skew in all cases, e.g.
(let [old-a (ensure a)] ...
Rich
They don't conflict, but you are correct that Clojure's STM currently
doesn't leverage that fact. It is my intention that at some point it
will, so please use ensure rather than dummy writes.
Rich