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