C# - Where is Lock Appropriate to Use in Libraries?

c#, locking, multithreading

Solution

If you're designing data structures and types that needs to have a guarantee about thread safety, then sure, put locks and other constructs into those types to uphold those guarantees.

However, locks alone isn't enough.

Take a simple dictionary. Let's say you want to ensure the internal data structure inside the dictionary cannot be corrupted by multiple threads, so you introduce locks. However, if the outside code does this:

if (!dict.ContainsKey(key))
    dict.Add(key, value);

Then there is no guarantee here that between the call to `ContainsKey` and `Add`, some other thread hasn't already added that key to the dictionary.

As such, thread-safe types may entail more things than simple locks. A method that can safely add the key and value to the dictionary if it's not already there, in an atomic operation, and then return a flag telling you what it did, may be needed.

In fact, look here: ConcurrentDictionary.TryAdd.

My advice would be this:

- If you need those guarantees, design the type to be thread-safe by going through the scenarios that needs to be safe, and predictable, and implement those specifically

- If you don't need those guarantees, don't bother doing anything, instead simply document that the type is not thread-safe, leave that to the code that uses it

The .NET type `List` does not use locks in any way, except for a few select places where thread safety is a concern, specifically the SyncRoot property.

Additionally, writing good thread-safe data types isn't easy. Just throwing in locks everywhere you need them will probably make it more thread-safe, but you will pay a hefty penalty in terms of performance. If a program doesn't need it to be thread-safe when it uses it, you still pay a lot of that price.

Writing performant thread-safe types is harder, and does usually not rely on locks (alone), but instead uses things like spin-waits, specific CPU instructions (some of which are available to .NET code), etc. But this needs highly specialized knowledge about how modern CPU's execute code.

If I were you I would leave thread-safety to the experts, and drop it from your own types, unless you absolutely need it.

Problem

I'm writing a library for multiple projects. And it contains classes that contain and manipulate data. So I thought I should lock this data while a method of those classes is executed. But I also thought if thread safe data manipulation must be done, then let the higher application layer handle locking. What would be the best practice for a library of classes to be used by actual applications later. Let's say I have a class `SpecialList`. What do I do: - lock data when methods are called - let the user lock the list if he needs thread safety + ignore (index) exceptions so the user must catch them ? If I knew how the .NET Framework class `List` handles that I would do the same. The classes are not explicitly targeted at single- or multi-threading. They are just helping classes for all kinds of uses.

Original source