Should thread-safe class have a memory barrier at the end of its constructor?

前端 未结 4 1887
终归单人心
终归单人心 2020-12-03 17:08

When implementing a class intended to be thread-safe, should I include a memory barrier at the end of its constructor, in order to ensure that any internal structures have c

相关标签:
4条回答
  • 2020-12-03 17:47

    No, you don't need memory barrier in the constructor. Your assumption, even though demonstrating some creative thought - is wrong. No thread can get a half backed instance of queue. The new reference is "visible" to the other threads only when the initialization is done. Suppose thread_1 is the first thread to initialize queue - it goes through the ctor code, but queue's reference in the main stack is still null! only when thread_1 exists the constructor code it assigns the reference.

    See comments below and OP elaborated question.

    0 讨论(0)
  • 2020-12-03 18:01

    Lazy<T> is a very good choice for Thread-Safe Initialization. I think it should be left to the consumer to provide that:

    var queue = new Lazy<ThreadSafeQueue<int>>(() => new ThreadSafeQueue<int>());
    
    Parallel.For(0, 10000, i =>
    {
    
        else if (i % 2 == 0)
            queue.Value.Enqueue(i);
        else
        {
            int item = -1;
            if (queue.Value.TryDequeue(out item) == true)
                Console.WriteLine(item);
        }
    });
    
    0 讨论(0)
  • 2020-12-03 18:01

    In answer to your simplified question:

    ConcurrentQueue<int> queue = null;
    
    Parallel.Invoke(
        () => queue = new ConcurrentQueue<int>(),
        () => queue?.Enqueue(5));
    

    It is definitely possible that your code could try to call queue.Enqueue(5) before queue has a value, but it isn't anything you could protect against from within the constructor of Queue. queue won't actually be assigned a reference to the new instance until the constructor completes.

    0 讨论(0)
  • 2020-12-03 18:06

    Unrelated, but still interesting that in Java for all final fields that are written inside the constructor there would two fences written after the constructor exists: StoreStore and LoadStore - that would make publishing the reference thread-safe.

    0 讨论(0)
提交回复
热议问题