英特尔检查器报告我的螺旋锁实现中的数据竞争

Gra*_*Lup 8 c++ winapi synchronization spinlock intel-inspector

我使用Windows中的Interlocked函数制作了一个非常简单的自旋锁,并在双核CPU上测试它(两个线程增加一个变量);

该程序似乎工作正常(它每次都给出相同的结果,但不使用同步时不是这种情况),但英特尔Parallel Inspector表示存在值+ = j的竞争条件(参见下面的代码).使用Critical Sections而不是SpinLock时,警告消失.

我的SpinLock实现是否正确?这真的很奇怪,因为所有使用的操作都是原子操作并且具有适当的内存屏障,并且不应该导致竞争条件.

class SpinLock
{
   int *lockValue;
   SpinLock(int *value) : lockValue(value) { }

   void Lock() {
      while(InterlockedCompareExchange((volatile LONG*)lockValue, 1, 0) != 0) {
          WaitABit();
      }
   }

   void Unlock() { InterlockedExchange((volatile LONG*)lockValue, 0); }
};
Run Code Online (Sandbox Code Playgroud)

测试程序:

static const int THREADS = 2;
HANDLE completedEvents[THREADS];
int value = 0;
int lock = 0; // Global.

DWORD WINAPI TestThread(void *param) {
    HANDLE completed = (HANDLE)param;
    SpinLock testLock(&lock);

    for(int i = 0;i < 1000*20; i++) {
        for(int j = 0;j < 10*10; j++) {
            // Add something to the variable.
            testLock.Lock();
            value += j;
            testLock.Unlock();
        }
    }
    SetEvent(completed);
}

int main() {
   for(int i = 0; i < THREADS; i++) {
        completedEvents[i] = CreateEvent(NULL, true, false, NULL);
   }
   for(int i = 0; i < THREADS; i++) {
        DWORD id;
        CreateThread(NULL, 0, TestThread, completedEvents[i], 0, &id);
   }

   WaitForMultipleObjects(THREADS, completedEvents, true, INFINITE);
   cout<<value;
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*ham 4

Parallel Inspector 的数据竞争文档建议使用关键部分或互斥体来修复 Windows 上的竞争。其中没有任何内容表明 Parallel Inspector 知道如何识别您可能发明的任何其他锁定机制。

用于分析新颖锁定机制的工具往往是静态工具,它们会查看代码中的每个可能路径,Parallel Inspector 的文档暗示它只执行一次代码。

如果您想尝试新颖的锁定机制,我在学术文献中看到的最常用工具是Spin model checker。还有ESP,它可能会减少状态空间,但我不知道它是否已应用于并发问题,还有移动工作台,如果您可以用 pi 演算来表达您的问题,它将进行分析。英特尔 Parallel Inspector 似乎并不像这些工具那么复杂,而是旨在使用启发式方法检查常见问题。