How to make a non thread safe 3rd party library actually thread safe?

I have a 3rd party library that offers a class. Their documentation says:

Thread Safety

Public static (Shared in Visual Basic) members of this type are safe for multithreaded operations. Instance members are not guaranteed to be thread-safe.

I did some testing where I created 100 threads. Indeed there are thread safety issues if I pass the same object to all 100 threads, but those problems appear to go away if each thread creates its own instance of the class.

I'm using .NET 4.0 here. In my application there are multiple threads that will want to use this class, but I don't want to create and destroy the objects more than necessary (they should live for the lifetime of the application), so I want one per thread. Is this an appropriate use of the ThreadLocal<T> class? If not, what is the standard way to handle this?

Edit:

Some more information about the 3rd party class. It's a communication library and opens a communication link to another process, either on this computer or another computer. The other end of the communication link is designed to accept concurrent connections. Therefore I shouldn't need to synchronize the method calls on my end by using locks. However, each instance is not thread safe.

Jon Skeet
people
quotationmark

Assuming you don't need the objects to interact with each other at all, ThreadLocal<T> is a very good choice here. It obviously doesn't work if modifications made in one thread are meant to be seen in another thread, just safely.

Yes, it will create one object per thread - but unless creating the objects is really expensive, you're likely to have on the order of hundreds of instances, which in most cases is absolutely fine.

One classic example of this is System.Random:

  • You don't want to create instances on an ad hoc basis, as if you're not careful you'll end up with multiple instances with the same seed
  • It's definitely not thread-safe.

So you could do something like:

public static class RandomProvider
{
    private static readonly Random seedProvider = new Random();

    private static readonly ThreadLocal<Random> threadLocal =
        new ThreadLocal<Random>(InitializeNewRandom);

    public static Random GetRandomForThread()
    {
        return threadLocal.Value;
    }

    private static Random InitializeNewRandom()
    {
        lock(seedProvider)
        {
            return new Random(seedProvider.Next(int.MaxValue));
        }
    }
}

An alternative would be to write a thread-safe proxy class which used locking for each operation - but that still has issues if you have multiple operations which you wish to execute "atomically" (i.e. without interleaving other calls).

people

See more on this question at Stackoverflow