Free mag vol1 | Page 778

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING shared resources. As you would guess, the System.Threading namespace provides a number of synchronization-centric types. The C# programming language also provides a particular keyword for the very task of synchronizing shared data in multithreaded applications. Synchronization Using the C# lock Keyword The first technique you can use to synchronize access to shared resources is the C# lock keyword. This keyword allows you to define a scope of statements that must be synchronized between threads. By doing so, incoming threads cannot interrupt the current thread, thus preventing it from finishing its work. The lock keyword requires you to specify a token (an object reference) that must be acquired by a thread to enter within the lock scope. When you are attempting to lock down a private instance-level method, you can simply pass in a reference to the current type, as follows: private void SomePrivateMethod() { // Use the current object as the thread token. lock(this) { // All code within this scope is thread safe. } } However, if you are locking down a region of code within a public member, it is safer (and a best practice) to declare a private object member variable to serve as the lock token, like so: public class Printer { // Lock token. private object threadLock = new object(); public void PrintNumbers() { // Use the lock token. lock (threadLock) { ... } } } In any case, if you examine the PrintNumbers() method, you can see that the shared resource the threads are competing to gain access to is the console window. Therefore, if you scope all interactions with the Console type within a lock scope, as follows: public void PrintNumbers() { // Use the private object lock token. lock (threadLock) { // Display Thread info. Console.WriteLine("-> {0} is executing PrintNumbers()", Thread.CurrentThread.Name); 723