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.

Sign up to vote on this title
UsefulNot useful