If you have read the awesome book by Jeffrey Richter CLR via C# 4 ed. you have discovered that there are more optimal ways for thread synchronization than the one provided by the BCL. One of them is the use of new asynchronous capabilities in order to create an asynchronous synchronization primitive. In the book it is presented an AsyncOneManyLock which is used for thread synchornization for code with a high demand for responsiveness and scalability.
If you are an F# developer you know that the F# Asynchornous Workflow and the Task Parallel Library are different, so I decided to port this useful piece of code to F# and show you how to use it with an example.
You can download the source code from here.
A simple example of usage of AsyncOnManyLock, we try to synchronize the access to a shared list from different kind of consumers as follows:
open System open System.Collections.Generic open System.Threading open System.Threading.Tasks open AP.Threading [The example creates three concurrent tasks that try to access a shared list to read/delete or update the contained items. If the access is of read type then a simple shared lock is sufficient, but in order to modify the list you must access the lock in an exclusive mode. In order to use the TPL with the Async builder you must pass the Task to the Async.AwaitTask function.] let main argv = let asyncOneManyLock = new AsyncOneManyLock() let rnd = new Random() let col = new List () col.Add(1) async { while(true) do let! discard = asyncOneManyLock.WaitAsync(OneManyMode.Shared) |> Async.AwaitTask let elem = col |> Seq.head printfn "col[0]=%d; col.Count=%d" elem col.Count asyncOneManyLock.Release() } |> Async.Start async { while(true) do Thread.Sleep(rnd.Next(10000)) let! discard = asyncOneManyLock.WaitAsync(OneManyMode.Exclusive) |> Async.AwaitTask let numOfElement = rnd.Next(col.Count - 1) if numOfElement > 0 then col.RemoveRange(0, numOfElement) asyncOneManyLock.Release() } |> Async.Start async { while(true) do let! discard = asyncOneManyLock.WaitAsync(OneManyMode.Exclusive) |> Async.AwaitTask col.Insert(0, rnd.Next()) asyncOneManyLock.Release() } |> Async.RunSynchronously 0
That's all, now you can benefit of a highly efficient, not blocking, threat synchronization component.