线程安全测试/减少

时间:2015-07-23 14:26:06

标签: multithreading delphi freepascal lazarus

此代码线程是否安全,或者在执行InterLockedDecrement之前是否可以通过另一个线程更改FCount?

procedure TMyObject.Wait;
begin
  if FCount > 0 then
    InterLockedDecrement(FCount);
  ..
end;

3 个答案:

答案 0 :(得分:5)

代码不是线程安全的。 writeDisposition声明中的FCount读取比赛。

由于我不知道您的代码要实现的目标,更大的目标是什么,我不会建议解决方案。

答案 1 :(得分:5)

这不是线程安全的。

  • 线程1读取FCount = 1,将条件评估为True。
  • 线程2读取FCount = 1,将条件评估为True。
  • 线程1将FCount减少为0
  • 线程2将FCount减少为-1

但我认为该代码专门用于防止将FCount降低到零以下。

您可能需要考虑以下内容:

if InterlockedDecrement(FCount) < 0 then
  InterlockedIncrement(FCount);

这样,两个并发线程中的一个会将值减小为-1,然后“修复它的错误” 但是,它确实会产生FCount可能暂时为< 0的副作用。

答案 2 :(得分:1)

其他人已经指出,这不是线程安全的。如果你想确保代码减少FCount的值,如果它大于0,那么你可以使用这样的东西而不用锁定:

procedure TMyObject.Wait;
var
  count: Integer;
  countPlus1: Integer;
begin
  repeat
    count := FCount;
    if (count > 0) then
    begin
      countPlus1 := count; 
      Dec(count);
    end;
  until (count <= 0) or (InterlockedCompareExchange(FCount, count, countPlus1) = countPlus1);
  ..
end;