我有一个提供课程的第三方图书馆。他们的文件说:
线程安全
此类型的公共静态(在Visual Basic中为Shared)成员对于多线程操作是安全的。实例成员不保证是线程安全的。
我做了一些测试,我创建了100个线程。事实上,如果我将同一个对象传递给所有100个线程,就会出现线程安全问题,但如果每个线程都创建了自己的类实例,那么这些问题似乎就会消失。
我在这里使用.NET 4.0。在我的应用程序中有多个线程需要使用这个类,但我不想创建和销毁对象超过必要的(它们应该在应用程序的生命周期中存活),所以我想要每个线程一个。这是ThreadLocal<T>
类的适当用法吗?如果没有,处理这个问题的标准方法是什么?
修改:
有关第三方课程的更多信息。它是一个通信库,可以在此计算机或其他计算机上打开与另一个进程的通信链接。通信链路的另一端旨在接受并发连接。因此,我不需要使用lock
来同步我的方法调用。但是,每个实例都不是线程安全的。
答案 0 :(得分:3)
假设您不需要对象完全相互交互,ThreadLocal<T>
在这里是一个非常好的选择。如果在一个线程中进行的修改意味着在另一个线程中被看到,那么它显然不起作用,只是安全。
是的,它会为每个线程创建一个对象 - 但除非创建对象真的昂贵,否则你很可能拥有数百个实例的订单,在大多数情况下这些实例绝对没问题
一个典型的例子是System.Random
:
所以你可以这样做:
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));
}
}
}
另一种方法是编写一个线程安全的代理类,它为每个操作使用锁定 - 但如果你有多个你希望“原子地”执行的操作(即没有交错其他调用),那么仍会出现问题。
答案 1 :(得分:0)
我认为在这个类上面创建一个使用Monitors(lock关键字)或其他线程阻塞同步构造来阻止所有操作的包装器可以提供帮助。
但它并不能保证没有可能的死锁和竞争条件。如果没有完全重写原始类及其使用者,您可能仍会遇到问题。
在后处理过程中,您无法确保安全和不安全的安全。首先必须考虑这些品质,这甚至不是你的图书馆。