In the previous example, we saw how to manage simple counter state using atomic operations. For more complex state, we can use a mutex to safely access data across multiple threads.
Running the program shows that the counters updated as expected.
In this C# version, we’ve made the following adaptations:
We use a Dictionary<string, int> instead of a map.
The Mutex is replaced with C#’s lock keyword and a private object for synchronization.
Instead of goroutines, we use C#’s Task-based asynchronous programming model.
The WaitGroup is replaced by Task.WhenAll(), which waits for all tasks to complete.
We’ve added a GetCounters() method to safely retrieve the current state of the counters.
This example demonstrates how to use locks in C# to safely access shared state from multiple threads, achieving the same goal as the original example.
Next, we’ll look at implementing this same state management task using only tasks and channels (which in C# would typically be implemented using producer-consumer patterns with collections like BlockingCollection<T> or channels from the System.Threading.Channels namespace).