在If条件中使用Interlocked.Decrement,是否会导致任何并发问题?

时间:2017-03-23 14:15:23

标签: c# multithreading thread-safety .net-3.5

我正在创建一个自定义的CountdownWaitHandle类,它有以下方法:

public void Signal()
{
    if (Interlocked.Decrement(ref threadsInstances) <= 0)
    {
        mre.Set();
    }
}

mre是ManualResetEvent类的一个实例,我使用这个类来阻塞当前线程并等待所有线程完成他的工作和每个线程完成他的工作或发生异常调用Signal()方法。

所以我的问题是,Interlock.Decrement和condition(&lt; = 0)的返回值是否可能导致内部任何并发问题?如果条件?或者我必须对if条件使用lock语句如果身体代替Interlock,就像上面的例子那样:

 lock(_lock)
   {
        if (--threadsInstances <= 0)
        {
            mre.Set();
        }   
   }

注意:我使用3.5 net。

完整代码:

 public class CountdownWaitHandle : WaitHandle
    {    
        private int threadsInstances = 0;            
        private ManualResetEvent mre;    
        private readonly object threadsyncAccess = new object();

        public CountdownWaitHandle(int initialCount)
        {
            threadsInstances = initialCount;
            mre = new ManualResetEvent(false);
        }

        public void AddCount()
        {
            Interlocked.Increment(ref threadsInstances);
        }

        public void Signal()
        {
            if (Interlocked.Decrement(ref threadsInstances) <= 0)
            {
               mre.Set();
            }
        }

        public override bool WaitOne()
        {
            return mre.WaitOne();
        }   

    }

在这个例子中。
我将使用我的自定义CountdownEvent类来下载一个大的 使用任何云站点的块的文件。因此,在完成下载其范围字节后的每个块,它释放资源或移动到另一个流。

public static void Main(String[] args)
   {          

        CountdownWaitHandle customCountDown = new CountdownWaitHandle(0)               

                    while (i < 100)
                    {

                        SpecificWork work1  = new SpecificWork (startPosition, endPosition, customCountDown);
                        customCountDown.AddCount();                                                       
                        ThreadPool.QueueUserWorkItem(PerformTask, work1); //  after finish download it invokes to Signal method. 
                    }
                    customCountDown.WaitOne();
                }

1 个答案:

答案 0 :(得分:0)

假设您正在调用Interlocked.Decrement将计数提高到零以上,

Interlocked.Increment将按照此示例中的预期工作。

当然,使用CountdownEvent会比构建自己的同步对象更好。