【问题标题】:Implementing a bitwise operation using the Interlocked class in .NET使用 .NET 中的 Interlocked 类实现按位运算
【发布时间】:2015-07-27 15:21:28
【问题描述】:

我正在尝试在多线程 .NET 应用程序中的共享变量中设置位标志,但在托管 Interlocked 类中找不到与本机 InterlockedOr 函数的并行。我想出了以下代码来执行 |= 赋值,但理论上无限循环的可能性让我感到不舒服:

long currentValue;
long updatedValue;

do
{
    // Spin until successful update. Value must be read using Interlocked.Read()
    // to be truly atomic on 32 bit systems (see MSDN).
    currentFlags = Interlocked.Read(ref _currentFlags);
    updatedValue = currentFlags | flag;
} while (currentFlags != Interlocked.CompareExchange(ref _currentFlags, updatedValue, currentFlags));

是否可以仅使用 Interlocked 类中内置的函数以更安全的方式实现?如果可能,我想避免涉及显式锁定的解决方案。

【问题讨论】:

  • 虽然在使用CompareExchange 时可能会出现无限循环,但这种情况不太可能发生,可以忽略不计。 .NET Framework 广泛使用了这种技术,包括在所有并发集合中以实现无锁同步。
  • 只有当其他线程同时将标志重置为零时,您才会获得无限循环,并且足够灵活,每次都可以击败您的线程,进行无限次尝试。如果发生这种情况,你有更大的问题需要解决,弄清楚为什么“敏捷”线程会做它所做的事情。我认为您的解决方案与Interlocked 一样好。

标签: c# .net multithreading bit-manipulation interlocked


【解决方案1】:

让我们假设(这些限制不是基本的,只是为了简化说明)

  • 开头currentFlags0
  • 我们一步最多设置一个标志,
  • 我们不接触符号位。

请注意,如果我们在currentFlags 中将位k 设置为1 一次,我们可以将or 替换为+ 1L << k。所以我们可以使用辅助数组 set 来记住已经设置了哪些位,如果需要,可以使用 Interlocked.Add

long currentFlags = 0;
int[] set = new int[sizeof(long) * 8];

....

int k = ...; // bit to set
if(Interlocked.Exchange(ref set[k], 1) == 0)
    Interlocked.Add(ref currentFlags, 1L << k);

【讨论】:

    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 2021-09-13
    • 2013-05-28
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    相关资源
    最近更新 更多