线程安全测试/递减

Threadsafe test / decrement

这段代码是线程安全的吗,或者 FCount 是否可以在执行 InterLockedDecrement 之前被另一个线程更改?

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

代码不是线程安全的。在 if 语句中读取 FCount 存在竞争。

因为我不知道你的代码想要实现什么,更大的目标是什么,所以我不会提出解决方案。

它不是线程安全的。

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

但我假设该代码专门用于防止将 FCount 减少到零以下。

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

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

这样,两个并发线程中的一个将值减为-1,然后"fix its mistake"。
但是,它确实有 FCount 可能暂时 < 0.

的副作用

正如其他人指出的那样,它不是线程安全的。如果你想确保代码减少 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;