You are on page 1of 13

Lazy Synchronization Methods

Things to watch out for


Don Stewart | Galois Dev Symposium | Feb 2010

2008 Galois, Inc. All rights reserved.


Control.Concurrent.*

• A set of abstractions for thread


communication and synchroniztion
– Mvar – synchronizing variables
– Chan – unbounded channels
• Simple, clean semantics makes
concurrency easy

2008 Galois, Inc. All rights reserved.


But beware of
evaluation strategies!
• putMVar
– fills an Mvar with a value
– but doesn't force evaluation
– so mostly you're just putting a pointer to a
closure in there
• The thread 'take'ing the message gets the
nasty surprise of having to evaluate the
message! Work gets done in the wrong
place
2008 Galois, Inc. All rights reserved.
Manual fixes

• putMVar mv $! x + 1
– ok for “atomic” types (one depth of
constructors)

• Harder for normal forms:


– let x' = x + 1 in rnf x `seq` putMVar mv x

2008 Galois, Inc. All rights reserved.


Same risks hold for...

• IORef
• Mvar
• Chans (lists of Mvars)
• Semaphores...
• Data.Map.insertWith...

2008 Galois, Inc. All rights reserved.


More insidious...

• modifyMVar considered harmful!

– ex1.hs

2008 Galois, Inc. All rights reserved.


Seen in the wild...

Seen in a production system

newUnique (US ref) = atomicModifyIORef ref $ \u ->


let !u' = u+1 in (u', Unique u)

This catches even the best programmers!


(And worse with the atomic* functions)

2008 Galois, Inc. All rights reserved.


One way to fix it...

• ex2.hs
• mean 68.3ms, 451us std dev.

2008 Galois, Inc. All rights reserved.


A big hammer

• RNF-by-default for synchronization


variables!
– cabal install strict-concurrency
• First library I wrote at Galois. :-)

• ex3.hs

2008 Galois, Inc. All rights reserved.


Timings

• mean: 61.7ms, 2ms std dev!

2008 Galois, Inc. All rights reserved.


import
Control.Concurrent.MVar.Strict
• ex4.hs

• Raises the issue: rnf can be very heavy (a


traversal on every commit!)
• Often wasting work. Need an 'rnf' bit...
– (see Andy Gill's proposal)

2008 Galois, Inc. All rights reserved.


Lessons

• Be careful with modify* functions


• Be careful with lazy synchronization
– work gets migrated around
• In general,
– always use putMVar mv $! …
– always use strict channels, or manually
evaluate before putting into the channel

2008 Galois, Inc. All rights reserved.


Addtionally...

• block/unblock on exceptions can be really


subtle.
• Be careful!
• And threadDelay (or other thread stopping
methods) complicates block.
• Be careful with async messages +
synchronization!
2008 Galois, Inc. All rights reserved.

You might also like