13 Thread-safe collections

 

This chapter covers

  • The problems encountered when using regular collections in a multithreaded program
  • Concurrent collections
  • The BlockingCollection class
  • Asynchronous alternatives to Blocking-Collection
  • Immutable collections and special considerations when using them
  • Frozen collections

The System.Collections.Generic namespace contains many useful collections; however, we can’t just use them in a multithreaded application because all those collections are not thread safe. In this chapter, we’ll look at the problems with the simplest way of making collections thread safe—just putting a lock around any access to the collection. We’ll also talk about the thread-safe alternatives provided by the .NET library.

Specifically, we’ll examine the concurrent collections added in .NET framework 4, discuss the immutable collections added in .NET Core (which is the basis for .NET 5 and later), and talk about the frozen collections added in .NET 8. You will also learn how to use each type of collection and when it’s appropriate to do so. But first, let’s talk about why you can’t just use the regular collections.

13.1 The problems with using regular collections

The .NET library provides many useful collection classes in the System.Collections.Generic namespace. Those collections support multiple concurrent reads, but they can be corrupted and produce unexpected results if there are multiple concurrent writers or if different threads try to read and write simultaneously.

13.2 The concurrent collections

13.2.1 ConcurrentDictionary<TKey,TValue>

13.2.2 BlockingCollection<T>

13.2.3 Async alternatives for BlockingCollection

13.2.4 ConcurrentQueue<T> and ConcurrentStack<T>

13.2.5 ConcurrentBag<T>

13.2.6 When to use the concurrent collections

13.2.7 When not to use the concurrent collections

13.3 The immutable collections

13.3.1 How immutable collections work

13.3.2 How to use the immutable collections

13.3.3 ImmutableInterlocked

13.3.4 ImmutableDictionary<TKey,TValue>

13.3.5 ImmutableHashSet<T> and ImmutableSortedSet<T>

13.3.6 ImmutableList<T>

13.3.7 ImmutableQueue<T> and ImmutableStack<T>

13.3.8 ImmutableArray<T>