public static HashSet <string> thread safe?</string>

时间:2011-07-24 16:10:16

标签: c#

基本上我有一个应用程序调用3个不同的线程,每个新的HashSet和我想知道的是这个线程是否安全?或者我是否需要在每个哈希集中添加[ThreadStatic]?

2 个答案:

答案 0 :(得分:6)

如果您实例化三个不同的HashSet,并且每个HashSet只能由一个线程访问,那么它就没问题了。如果线程之间共享一个静态[ThreadStatic],则只需添加HashSet属性。

[更新] 只是为了澄清[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();
}

显示虽然只有一个测试实例,但每个线程都会获得一个新的hashset实例:

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'

答案 1 :(得分:4)

根据HashSet的MSDN文档:

  

此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。