开发者

public static HashSet<string> thread safe?

开发者 https://www.devze.com 2023-03-22 18:57 出处:网络
Basically i have an app c开发者_如何学Pythonalling 3 different threads that each that a new HashSet and I want to know is this thread safe?or do I need a [ThreadStatic] added to each hashset?If you in

Basically i have an app c开发者_如何学Pythonalling 3 different threads that each that a new HashSet and I want to know is this thread safe? or do I need a [ThreadStatic] added to each hashset?


If you instantiate three different HashSets, and each HashSet is accessed only by a single thread, then it will be fine. You only need to add the [ThreadStatic] attribute if there is a single static HashSet shared among threads.

[Update] Just to clarify how [ThreadStatic] would work.

Disclaimer: I never use [ThreadStatic]. The presence of that attribute has a lot of consequences which are not obvious and are hard to debug (as well as test properly) IMO.

Let's say you really want to use [ThreadStatic] in a test class:

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;
    }
}

Running the following console app:

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();
}

Shows that, although there is a single test instance, each thread gets a new instance of the 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'


According to the MSDN docs for HashSet:

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号