Multithreading 螺纹安全测试/减量

Multithreading 螺纹安全测试/减量,multithreading,delphi,freepascal,lazarus,Multithreading,Delphi,Freepascal,Lazarus,此代码是线程安全的,还是在执行InterlocatedDecrement之前,可以由另一个线程更改FCount procedure TMyObject.Wait; begin if FCount > 0 then InterLockedDecrement(FCount); .. end; 代码不是线程安全的。在if语句中读取FCount时存在争用 因为我不知道您的代码打算实现什么,更大的目标是什么,所以我不会建议解决方案 它不是线程安全的 线程1读取FCount=1,将条

此代码是线程安全的,还是在执行InterlocatedDecrement之前,可以由另一个线程更改FCount

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

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

因为我不知道您的代码打算实现什么,更大的目标是什么,所以我不会建议解决方案

它不是线程安全的

线程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。

它不像其他人指出的那样是线程安全的。如果要确保如果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;

我明白了,代码不是线程安全的。不幸的是,我模糊地怀疑,在调用InterlocatedDecrement之后,另一个线程可能在指定正确的值之前读取或更改FCount的值。否。不是这样。问题是if中的读取没有同步。因此,我应该使用一个关键部分来保护读取和增量?@Rimfire这取决于您试图实现的目标以及FCount的目的。我的建议是基于这样一个想法,即减少FCount很容易逆转。但是,如果您有其他基于读取或修改FCount的决策逻辑,则需要评估它是否会成为问题。您可以按照我的回答,一步一步地演练两个线程,以帮助您做出决定。但是只有您有这样做的信息。@Rimfire我不知道您如何在不向我们提出问题的情况下询问我们应该做什么。有关线程安全递减的示例,请参阅的源代码。