基本上我有一个应用程序调用 3 个不同的线程,每个线程都有一个新的 HashSet,我想知道这个线程安全吗?还是我需要将 [ThreadStatic] 添加到每个哈希集?
最佳答案
如果你实例化了三个不同的HashSet
,并且每个HashSet
只被一个线程访问,那么就没问题了。如果线程之间共享一个静态 HashSet
,则只需添加 [ThreadStatic]
属性。
[更新] 只是为了阐明 [ThreadStatic]
是如何工作的。
免责声明:我从不使用[ThreadStatic]
。该属性的存在会产生很多不明显的后果,并且很难调试(以及正确测试)IMO。
假设您真的想在测试类中使用 [ThreadStatic]
:
public class ThreadStaticTest
{
// CLR ensures that each thread accessing this field
// gets a separate instance of the *field*. This, however,
// means that static initializers don't work. Field is
// null at first access from an individual thread
[ThreadStatic]
static HashSet<string> _hashset;
// This is why we instantiate it explicitly here:
private HashSet<string> HashSet
{
get
{
_hashset = _hashset ?? new HashSet<string>();
return _hashset;
}
}
public void AddItem(string s)
{
// thread safe
HashSet.Add(s);
}
public IEnumerable<string> GetItems()
{
// thread safe
return HashSet;
}
}
运行以下控制台应用程序:
static void Main(string[] args)
{
// single test instance!
var test = new ThreadStaticTest();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 5; i++)
{
threads.Add(new Thread(() =>
{
var threadId = Thread.CurrentThread.ManagedThreadId;
test.AddItem("Hello from thread #" + threadId);
Console.WriteLine("Instance contains {0} items: '{1}'",
test.GetItems().Count(),
string.Join(", ", test.GetItems().ToArray()));
}));
}
threads.ForEach(t => t.Start());
threads.ForEach(t => t.Join());
Console.Read();
}
表明,虽然只有一个测试实例,但每个线程都会获得哈希集的一个新实例:
Instance contains 1 items: 'Hello from thread #11' Instance contains 1 items: 'Hello from thread #13' Instance contains 1 items: 'Hello from thread #10' Instance contains 1 items: 'Hello from thread #12' Instance contains 1 items: 'Hello from thread #14'
关于c# - public static HashSet<string> 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6807967/