简体   繁体   English

如何使非线程安全的第三方库实际上是线程安全的?

[英]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. 此类型的公共静态(在Visual Basic中为Shared)成员对于多线程操作是安全的。 Instance members are not guaranteed to be thread-safe. 实例成员不保证是线程安全的。

I did some testing where I created 100 threads. 我做了一些测试,我创建了100个线程。 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. 实际上,如果我将相同的对象传递给所有100个线程,则存在线程安全问题,但是如果每个线程创建自己的类实例,那么这些问题似乎就会消失。

I'm using .NET 4.0 here. 我在这里使用.NET 4.0。 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? 这是ThreadLocal<T>类的合适用法吗? 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 lock s. 因此,我不需要使用lock s来同步我的方法调用。 However, each instance is not thread safe. 但是,每个实例都不是线程安全的。

Assuming you don't need the objects to interact with each other at all , ThreadLocal<T> is a very good choice here. 假设你不需要的对象彼此在所有互动, ThreadLocal<T>这里是一个非常不错的选择。 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 : 一个典型的例子是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" (ie without interleaving other calls). 另一种方法是编写一个线程安全的代理类,它为每个操作使用锁定 - 但如果你有多个你希望“原子地”执行的操作(即没有交错其他调用),那么仍然存在问题。

I think that making a wrapper above this class which blocks all operations with Monitors( lock keyword) or other thread blocking sync construct can help. 我认为在这个类上面创建一个使用Monitors(lock关键字)或其他线程阻塞同步构造来阻止所有操作的包装器可以提供帮助。

But it does not guarantee absence of possible deadlocks and race conditions. 但它并不能保证没有可能的死锁和竞争条件。 Without complete rewrite of the original class and its consumers you may still run into a problem. 如果没有完全重写原始类及其消费者,您可能仍会遇到问题。

You can't make unsafe thing safe and unsecure thing secure in postprocessing. 在后期处理中,你不能使不安全的东西安全且不安全。 Such qualities must be considered at first and this is even not your library. 首先必须考虑这些品质,这甚至不是你的图书馆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM