我有一个超短计数器(偶尔会翻过来)。使用此值的消息传递协议不允许 0。我需要一些线程安全的方法来每次读取此计数器(存储在类字段中)递增,如果我将其存储为 int 并使用互锁。增量。但是,我不确定如何将跳过 0 纳入其中。偶尔跳过几个数字也没关系;我的输出序列不一定是完美的。我不能在任何 4000 块中重复使用相同的数字。我想避免使用锁。
问问题
649 次
1 回答
4
这个:
鉴于:
static int value = ushort.MaxValue;
在代码中:
int temp, temp2;
do
{
temp = value;
temp2 = temp == ushort.MaxValue ? 1 : temp + 1;
}
while (Interlocked.CompareExchange(ref value, temp2, temp) != temp);
您必须使用 anint
然后对其进行强制转换(例如在get
属性中),因为Interlocked
并非适用于所有基本类型。
我们可能会在像这样的高度线程化的上下文中让它更快一点:
int temp = value;
while (true)
{
int temp2 = temp == ushort.MaxValue ? 1 : temp + 1;
int temp3 = Interlocked.CompareExchange(ref value, temp2, temp);
if (temp3 == temp)
{
break;
}
temp = temp3;
}
通过这种方式,我们必须少读一篇关于失败的文章。
正如我在评论中所写的,这段代码的中心思想是在一个临时变量 ( temp2
) 中增加计数器,然后尝试用新值 ( Interlocked.CompareExchange
) 交换我们知道的旧值。如果没有人触及 ( Interlocked.CompareExchange() == temp
) 之间的旧值,那么我们就完成了。如果其他人增加了该值,那么我们再试一次。通过使用具有固定最大值 ( )的ushort
来模拟。int
temp == ushort.MaxValue ? 1 : temp + 1
第二个版本,在失败时Interlocked.CompareExchange()
重用函数读取的值作为加 1 的新基础。
以这种Interlocked.CompareExchange
方式使用的可以用作构建其他Interlocked
操作的基础(你想要一个Interlocked.Multiply
?你做一个“标准”乘法然后尝试Interlocked.CompareExchange
旧值)
于 2013-09-03T19:45:30.317 回答