我可以混合使用InterlockedIncrement和CriticalSection吗?

时间:2015-10-02 10:30:54

标签: multithreading delphi

以前,我有这样的代码:

  EnterCriticalSection(q^);
  Inc(global_stats.currentid);
  LeaveCriticalSection(q^);

我改为:

InterlockedIncrement(global_stats.currentid);

我发现有一些这样的代码:

  EnterCriticalSection(q^);
  if (global_stats.currentid >= n) then
  begin
    LeaveCriticalSection(q^);
    Exit;
  end;
  LeaveCriticalSection(q^);

所以,问题是,我可以混合使用InterLockedIncrement和Enter / Leave CriticalSection吗?

哪个性能更快?关键和原子?

2 个答案:

答案 0 :(得分:4)

  

我可以混合使用InterLockedIncrement和Enter / Leave CriticalSection吗?

一般来说,不,你不能。关键部分和原子操作不会相互作用。

原子功能,例如您对InterLockedIncrement的调用,完全独立于关键部分和其他锁定。也就是说,一个线程可以保持锁定,另一个线程可以同时修改受保护的变量。与任何其他形式的互斥一样,关键部分仅在操作共享数据的所有各方都有效时才会起作用。

但是,从我们可以看到的代码来看,在这种情况下,关键部分是不必要的。您可以编写如下代码:

// thread A
InterlockedIncrement(global_stats.currentid);

....

// thread B
InterlockedIncrement(global_stats.currentid);

....

// thread C
if global_stats.currentid >= n then
  Exit;

该代码在语义上等同于具有关键部分的先前代码。

至于哪个表现更好,带锁的原始代码和上面的代码没有,后者预计会表现得更好。从广义上讲,可以预期无锁代码比使用锁的代码更好,但这不是可以依赖的规则。如果使用锁实现的某些算法比等效的无锁实现更快。

答案 1 :(得分:2)

不,一般情况下你不能。

关键部分用于确保所有受保护的代码块中最多只有一个在给定时刻执行。如果此类受保护块访问currentid并且该变量在其他位置被修改,则代码可能无法正常工作。

在特定情况下,混合和匹配可能没问题,但是你必须检查所有受影响的代码并重新考虑处理,这样你就不会发现任何问题。