Being Threadsafe - An Introduction to the Pitfalls of Parallelism |
Written by Mike James | ||||||
Friday, 31 May 2024 | ||||||
Page 2 of 5
Methods to make a thread safeThere are three general approaches to making code threadsafe:
Atomic operations and volatilityBefore moving onto more sophisticated ideas let’s consider some of the issues of low level data access. The .NET CLR guarantees that all native integer operations are atomic in the sense that these cannot be interrupted by a task swap in mid operation. This avoids the problem of a variable being changed by another thread in the middle of an operation so resulting in invalid or inconsistent data. The problem with this definition is that the native integer size varies according to machine type. So, is count++ an atomic operation? It all depends on the machine it is run on. If you want to be sure an operation is atomic then use the operations provided by the Interlocked class. For example, Interlocked.Increment(count); will add one to count without any risk that the process will be interrupted by another thread using a similar Interlocked operation. Notice that it can potentially be interrupted by standard non-interlocked operation. For this approach to work all of the threads have to use nothing but Interlocked operations to access shared resources. The advantage of Interlocked is simplicity; its disadvantage is that it is limited to the methods provided. In most cases it is much better to use a lock based on a Monitor, as described later. There is another strange problem associated with the way a variable changes its state or not. During a non-atomic operation a variable might change its state due to another thread. However, it is possible that the compiler and or machine architecture may make the assumption that a variable can’t change if the current thread doesn’t change it. This allows variables to be cached in fast memory but the cached copy may not reflect the true value of the variable stored in main memory. In practice this problem doesn’t happen at all often but you can declare a variable as volatile if you need the compiler to check that it hasn’t been changed by another thread. In practice it usually isn’t necessary to use volatile as, once again, if you use a lock it performs a volatile read at the start and a volatile write at the end making sure everything is up-to-date. <ASIN:B09FTLPTP9>
|
||||||
Last Updated ( Friday, 31 May 2024 ) |