简体   繁体   English

可以使用Interlocked.CompareExchange吗?

[英]Possible to use Interlocked.CompareExchange with a Bit?

I have an array of ints that track the completion of 10,000 concurrent tasks, where the value is either 1 or 0. I think it would be more efficient if this array was an array of Bits and each concurrent thread used interlocked.CompareExchange (or similar) to alter a single bit. 我有一个整数数组,该整数数组可以跟踪10,000个并发任务的完成,其值为1或0。我认为,如果此数组是一个Bits数组,并且每个并发线程使用互锁,则效率会更高。 )更改一位。

How should I approach this if Interlocked doesn't have an overload for "bit"? 如果“互锁”没有“位”的重载,我应该如何处理?

You can fake it with Interlocked.CompareExchange(ref int, int, int) in a loop, but I don't think it would be more efficient: 您可以在一个循环中使用Interlocked.CompareExchange(ref int, int, int)进行伪造,但我认为这样做不会更有效:

private static void SetBit(ref int valueToUpdate, int bitToSet)
{
   while (true)
   {
      int oldValue = valueToUpdate;
      int newValue = oldValue | bitToSet;
      int result = Interlocked.CompareExchange(ref valueToUpdate, newValue, oldValue);
      if (result == oldValue) break;
   }
}

I do not think you can do it with bits using Interlocked . 我不认为您可以使用Interlocked使用位。 You would have to switch to an array of ints , I believe, so that each bit is within its own int . 我相信,您将不得不切换到一个ints数组,以便每个位都在其自己的int

Interlocked.CompareExchange compares only for equality whereas you need to compare just a single bit of that int which you cannot do unless you use some other concurrency strategy to protect other changes to the int the bit resides within. Interlocked.CompareExchange仅比较是否相等,而您只需要比较该int一小部分,除非您使用其他并发策略来保护该int所在的int的其他更改,否则您无法进行比较。

You need thread-safe constructs to track the completion of the concurrent tasks. 您需要线程安全的构造来跟踪并发任务的完成。 Hence interlocked constructs are always faster than locks (because they don't need locks), you should use the static methods from the Interlocked -class with integers (0 as equivalent for false and 1 for true for example). 因此,互锁的构造总是比锁快(因为它们不需要锁),因此您应该使用Interlocked -class中的带有整数的静态方法(例如,0等同于false ,1等同于true )。

Jeffrey Richter does the same as he discribes in his book "CLR via C#" in chapter 28 "Primitive Thread Synchronization Constructs". 杰弗里·里希特(Jeffrey Richter)所做的与他在第28章“原始线程同步构造”中的“通过C#进行CLR”中的描述相同。 He introduces own lock implementations based on Interlocked constructs in his Wintellect.PowerThreading library as well and gives an excellent explanation as well as time comparisons of his own implementations and those included in the .net framework. 他还在Wintellect.PowerThreading库中介绍了基于互锁结构的自己的锁实现,并对自己的实现以及.net框架中的实现进行了出色的解释以及时间比较。

First, no, all Interlocked functions work on memory addresses, and individual bits are not addressable. 首先,不,所有互锁功能都在存储器地址上运行,并且单个位不可寻址。

So what to do instead? 那么该怎么做呢?

I would investigate two options: 我将研究两个选择:

  • don't bother with the array at all: have a simple counter, and InterlockedIncrement it each time a task completes. 根本不用理会数组:拥有一个简单的计数器,并在每次任务完成时对其进行InterlockedIncrement And to see if all tasks are done, just check if the value has reached 10,000 yet. 要查看所有任务是否已完成,只需检查该值是否已达到10,000。
  • alternatively, use the array, in order to minimize (false) data sharing. 或者,使用数组,以最小化(错误)数据共享。 But then you shouldn't try to pack it densely. 但是,您不应该尝试将其密集包装。 Go the opposite way. 相反。 Ensure that each entry ends up on a separate CPU cache line, so that tasks running in parallel won't fight over the same cache lines. 确保每个条目最终都位于单独的CPU高速缓存行上,以便并行运行的任务不会争夺相同的高速缓存行。 (And then, since tasks all write to separate locations, they won't even have to set their "done" flag with an expensive Interlocked operation.) (然后,由于所有任务都写入不同的位置,因此它们甚至不必通过昂贵的互锁操作来设置“完成”标志。)

I don't know which is fastest. 我不知道哪一个最快。 Benchmark it, if performance matters. 如果性能很重要,请进行基准测试。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM