c# - public static HashSet<string> 线程安全吗?

标签 c#

基本上我有一个应用程序调用 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/

相关文章:

c# - 无法通过警报调用 javascript 函数

c# - 如何使用 NodaTime 来将文化的 ShortDatePattern 转换为字符串格式?

c# - 使用参数和只放置一个变量然后转换它有什么区别

c# - Windows 上的套接字 - 我是否遗漏了程序中的某些内容?

c# - 我如何使用 for 或 while 循环以及在主体外部声明的 int?

c# - 如何使用 web.config 文件强制使用 HTTPS

c# - 如何查找包含 nunit 测试的 dll 文件

c# - 将通用 T1 转换为对象然后转换为 T2 是不好的做法吗?

c# - Ninject - 创建自定义 NinjectWebServiceHost

C# 不寻常的继承语法 w/generics