How can I set a min value in .Net without using a lock?

时间秒杀一切 提交于 2019-12-19 10:19:09

问题


I have multiple threads accessing variables. I know how to write spinlocks and use the Threading.Interlocked methods to increment etc. variables.

However, I want to perform the equivalent of:

a = Math.Min(a, b)
or
a = a | 10

... but without using a critical section. Is this possible? I know the 2nd line is possible in assembler, but there is no Interlocked.Or method.


回答1:


Here is the general pattern for simulating an interlocked operation.

public static T InterlockedOperation<T>(ref T location, T value)
{
  T initial, computed;
  do
  {
    initial = location;
    computed = op(initial, value); // initial | value
  } 
  while (Interlocked.CompareExchange(ref location, computed, initial) != initial);
  return computed;
}

The min operation is a completely different story. The issue here is that there are two memory locations in play. Furthermore, we are only interested in reading them. That means we really only need to worry about the memory barrier problem. Decorate your fields with volatile or do an explicit call to Thread.MemoryBarrier prior to computing the min.

Edit: I missed the fact that the result of the min operation is assigned to a. You can actually use the pattern I defined above, but instead of doing computed = initial | value do computed = initial < value ? initial : value. Everything else stays the same.




回答2:


If you don't anticipate a great deal of contention then perhaps something like this? (If there's likely to be a lot of contention then a plain lock might well be more efficient.)

int original;    // assuming here that a is an int
do
{
    original = a;
} while (Interlocked.CompareExchange(ref a, original | 10, original) != original)


来源:https://stackoverflow.com/questions/3731088/how-can-i-set-a-min-value-in-net-without-using-a-lock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!