You are on page 1of 3

Tutorial in using C# for handling monitoring process in threads (1)

Copied from :
http://www.cs.ubbcluj.ro/~vcioban/Bistrita/Manuale/Thinking.in.Csharp.pdf

Monitoring static value types


At this point, you shouldnt be surprised that this program quickly fails:
//How to synch a static value type? This program fails using System; using System.Threading; class RefCount1 { static int refCount = 0; static RefCount1() { ThreadStart ts = new ThreadStart(ValCheck); Thread t = new Thread(ts); t.Start(); } static void ValCheck() { Console.WriteLine("Starting ValCheck"); while (true) { Console.WriteLine(DateTime.Now); if (refCount != 0 && refCount != 1) { Console.WriteLine("Invalid: " + refCount); return; } Thread.Sleep(5000); } } //Chapter 16: Multithreaded Programming 749 RefCount1() { ThreadStart ts = new ThreadStart(Run); Thread t = new Thread(ts); t.IsBackground = true; t.Start(); } //Thread unsafe void Run() { Console.WriteLine("Starting RefCount"); while (true) {

refCount++; refCount--; } } public static void Main() { for (int i = 0; i < 2; i++) new RefCount1(); } }

The Run( ) method, which is used by a bunch of threads, increments and then decrements refCount, while a thread running the static delegate method ValCheck( ) stops the program if the value of refCount is ever not 0. When you run this, it is not long before refCount becomes either 2 or -1. This is what happens: 1. A RefCount instance thread increments refCount, making it 1. 2. That thread is interrupted by another thread, which increments refCount to 2. 3. The ValCheck( ) thread interrupts that thread and sees a value of 2. To synchronize access to the static value-type refCount, you have to wrap all access to the refCount object inside lock blocks that use some dummy object to synchronize on. You cannot lock (refCount) because its a value type. And lock (this) is ineffective on static objects! So you have to create a static dummy object to serve as a guard for the critical sections:
static SomeObject myDummyObject = new SomeObject(); static void ValCheck() { Console.WriteLine("Starting ValCheck"); while (true) { Console.WriteLine(DateTime.Now); lock(myDummyObject) { if (refCount != 0 && refCount != 1) { Console.WriteLine( "Invalid: " + refCount); return; } } Thread.Sleep(5000); } } void Run() { Console.WriteLine("Starting RefCount"); while (true) { lock(myDummyObject) { refCount++; refCount--; } } }

And indeed, thats the general solution to synchronizing static value types. For the specific problem of reference counting, however, the Interlocked class allows you to increment, decrement, and assign to an int or long in a thread-safe and very, very fast manner. It can also compare two ints or two longs without requiring the overhead of the Monitor implementation. Even aside from its synchronization capabilities, Interlocked should be used to generate serially increasing id values. Although
class StrangeButTrue { static int counter = 0; //Amazingly, this isn't thread-safe

public static int Next() { return counter++; //Chapter 16: Multithreaded Programming 751 } }

is fine for a single-threaded program, its not thread-safe, since the ++ operator reads and assigns the value in two separate operations. A thread can come along after the read but before the assignment and therefore, in a multithreaded program, Next( ) could return the same value twice.

You might also like