带有c#和TPL数据流的并发递增计数器模式

本文关键字:计数器 模式 并发 TPL 数据流 带有 | 更新日期: 2023-09-27 17:57:36

给定以下代码,在c#中并发访问时,计数++的行为如何:

 int count = 0;int Count=0;  
 ActionBlock<Tuple<CloudBlockBlob, CloudBlockBlob>> copyblock =
        new ActionBlock<Tuple<CloudBlockBlob, CloudBlockBlob>>(async (tuple) =>
            {
               await tuple.Item2.StartCopyFromBlobAsync(tuple.Item1);
               var progessDone = count++ / (double)Count;                  
               progress(progessDone,tuple.Item2.Name);
            },
            new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = ExecutionDataflowBlockOptions.Unbounded });

1) 有没有可能两个任务可以同时更新计数,这样两个读取然后两个写入都只递增一?2) 如果是,避免这种情况的最佳做法是什么?它周围的锁?

带有c#和TPL数据流的并发递增计数器模式

是的,这是完全可能的——至少在理论上是这样——但不,你不需要锁。只需使用Interlocked.Increment:

var progressDone = Interlocked.Increment(ref count) / (double) Count;

(根据您的CPU体系结构和JIT,增量最终可能是原子性的,这是有可能的,但肯定不能保证。即使是原子性,一个线程也有可能在没有内存障碍的情况下看不到另一个线程写入的值。Interlocked.Increment解决了所有这些问题,正是为这种情况而设计的。)