Free mag vol1 | Page 781

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING Synchronization Using the System.Threading.Interlocked Type Although it always is hard to believe until you look at the underlying CIL code, assignments and simple arithmetic operations are not atomic. For this reason, the System.Threading namespace provides a type that allows you to operate on a single point of data atomically with less overhead than with the Monitor type. The Interlocked class defines the following key static members shown in Table 19-4. Table 19-4. Select Static Members of the System.Threading.Interlocked Type Member Meaning in Life CompareExchange() Safely tests two values for equality and, if equal, exchanges one of the values with a third Decrement() Safely decrements a value by 1 Exchange() Safely swaps two values Increment() Safely increments a value by 1 Although it might not seem like it from the onset, the process of atomically altering a single value is quite common in a multithreaded environment. Assume you have a method named AddOne() that increments an integer member variable named intVal. Rather than writing synchronization code such as the following: public void AddOne() { lock(myLockToken) { intVal++; } } you can simplify your code via the static Interlocked.Increment() method. Simply pass in the variable to increment by reference. Do note that the Increment() method not only adjusts the value of the incoming parameter, but also returns the new value. public void AddOne() { int newVal = Interlocked.Increment(ref intVal); } In addition to Increment() and Decrement(), the Interlocked type allows you to atomically assign numerical and object data. For example, if you want to assign the value of a member variable to the value 83, you can avoid the need to use an explicit lock statement (or explicit Monitor logic) and make use of the Interlocked.Exchange() method, like so: public void SafeAssignment() { Interlocked.Exchange(ref myInt, 83); } 726