我有long? startTime
来保留开始时间。
我有多个具有非async
方法的线程,它们正在更新startTime
,并且在单独的线程中还有另一个async
方法,它只能读取该值。更新值的方法如下:
if (startTime == null || (newValue != 0 && newValue < startTime))
{
startTime = newValue;
}
问题在于,写线程正在以非常高的频率更新startTime
,从而导致了很多争用锁的情况。那么,有什么方法可以不用锁定(或者比普通锁定更好的锁定机制)来做到这一点?
我正在考虑使用Interlocked
,但是由于存在if
子句,我认为这是不正确的吗?
编辑:如果需要,我可以将其更改为不可为空的
。答案 0 :(得分:2)
问题结尾:
编辑:如果需要,我可以将其更改为不可为空的
。
对于不可为空的long
,您需要检查和更新循环(类似这样):
var current = Interlocked.Read(ref startTime);
while(current > newValue)
{
var other = Interlocked.CompareExchange(ref startTime, newValue, current);
if(other==current) break;
current = other;
}
您可以使while子句条件任意复杂,它们实际上是您的if
检查。您可能还希望/也需要在循环内重新计算newValue
。
Interlocked.Read
为您获取初始值。 Interlocked.CompareExchange
会执行“如果该值仍与我上次读取该值时相同,请提交更改”,如果该值已更改,则还会获取新的当前值。
要考虑的其他事项-您实际上是否需要此“开始时间”值,还是可以在其中放置一个简单的递增整数?那将是Interlocked.Increment
,没有循环且没有锁定,因此,如果您可以适当地修改代码的其他部分,那么这里的写争用仍然很高,可能值得考虑。