Stateless design
Just like in Java, designing classes without shared mutable state is the safest approach.
public class MyProcessor
{
public string Process(string input)
{
return input.ToUpper(); // No shared state
}
}
ThreadLocal
ThreadLocal is a .NET class that allows you to store data that is local to a specific thread. Each thread accessing a ThreadLocal instance gets its own independent copy of the data.
private static ThreadLocal<Random> random = new ThreadLocal<Random>(() => new Random());
public int GetRandomNumber()
{
return random.Value.Next();
}
Synchronized blocks
Use lock (or Monitor) to protect shared resources.
private readonly object _lock = new object();
private List<string> _sharedList = new List<string>();
public void AddItems(List<string> items)
{
lock (_lock)
{
_sharedList.AddRange(items);
}
}
ReentrantLock — More powerful, flexible locking with timeout
ReentrantLock lock = new ReentrantLock();
try {
acquired = lock.tryLock(500, TimeUnit.MILLISECONDS);
if (acquired) {
System.out.println("Lock acquired, doing work...");
// critical section
Thread.sleep(1000); // simulate work
} else {
System.out.println("Could not acquire lock within timeout.");
}
} finally {
lock.unlock();
}
ReentrantReadWriteLock — More powerful and more flexible, providing two locks - readLock and writelock with timeout, Effect: Multiple threads can read concurrently. Only one thread can write, and it blocks all readers.
Concurrency: Much better for read-heavy workloads.
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
public String read(String key) {
readLock.lock();
try {
return sharedMap.get(key);
} finally {
readLock.unlock();
}
}
public void write(String key, String value) {
writeLock.lock();
try {
sharedMap.put(key, value);
} finally {
writeLock.unlock();
}
}
Thread-safe collections
Thread-safe collections are designed to handle concurrent access without requiring manual locking.
Common Thread-Safe Collections in .NET
Collection Use Case
ConcurrentDictionary Key-value store with safe concurrent access
ConcurrentQueue FIFO queue for producer-consumer scenarios
ConcurrentStack LIFO stack for concurrent access
ConcurrentBag Unordered collection for fast insert/retrieve
BlockingCollection Thread-safe wrapper for producer-consumer with blocking and bounding
Partitioning
Similar to Spring Batch partitioning, you can divide work into chunks and assign each to a separate thread or task.
Parallel.ForEach(partitions, partition =>
{
ProcessPartition(partition);
});
Immutable data
Immutable types are inherently thread-safe. You can use records or readonly structs in C#.
public record Person(string Name, int Age);
Top comments (0)