[Mono-devel-list] Double-locking and thread safety
bmaurer at ximian.com
Thu Jun 23 13:12:20 EDT 2005
On Thu, 2005-06-23 at 19:03 +0200, Kornél Pál wrote:
> 1. Declaring "a" as volatile would solve the problem but it results in
> performance loss because of memory barriers for each read.
Well, the performance loss here isn't all that bad. On an x86 machine
there is basically no loss.
> 2. Removing the check outside the lock would solve the problem but it
> results in performance loss because of memory barriers for each read.
The real problem is that the lock can result in contention which is
orders of magnitude worse than a memory barrier.
> I think using a lock is better than constructing a new instance because the
> new instance would be dropped if it's already created as we want to use a
> single instance so it's better to suspend the thread by doing a wait than
> creating a new instance because the CPU time can be used for useful
> operations instead of wating time.
That issue only happens in the *VERY* rare case that two threads are
> "Realize that synchronization is expensive. The full fence implied by
> Interlocked.Increment can be many 100’s of cycles on modern hardware. That
> penalty may continue to grow, in relative terms."
> I think this applies to Interlocked.CompareExchange as well.
But that only gets run once per program. Anyways the cost of reading a
page in from the disk to do the Locale stuff is orders of magnitude more
> So I suggest to use this model instead of Interlocked.CompareExchange.
> Furthermore I think using two Thread.MemoryBarrier() is less effective than
> using lock and and a single Thread.MemoryBarrier() because there will be not
> useless object creation, Thread.MemoryBarrier() allways does a full barrier
> while lock does acrique at the begining and release at the end and
> Interlocked.CompareExchange does barriers as well so there are more barriers
> and thus locks in your "lock-free" code than in the locked code.
It depends on how commonly this code is used. The code is going to
become horrible to maintain if we have MemoryBarriers scattered around.
We should really stick to obvious locking patterns except where
performance is an issue. Now, given that this code is only used in
exceptional code paths (and in SWF -- but there, speed is measured in UI
responsiveness, and none of the solutions are slow enough to make a
difference there), the simple lock-then-check should suffice for now.
More information about the Mono-devel-list