竞争检查
数据竞争检测基本原理
happens-before
事件 a 发生在 b 之前定义为 a → b。以下三种条件都满足 a → b:
- a和b是同一个进程内的事件,a发生在b之前,则 a → b。
- a和b在不同的进程中,a是发送进程内的发送事件,b是同一消息接收进程内的接收事件,则 a → b。
- 如果a → b并且b → c,则a → c。
当两个或多个线程访问同一个共享变量(同一线程内需要保证有序执行),两个访存操作不在同一个线程中,并且不满足关系happens-before 关系即为数据竞争。
通过逻辑时钟计算 happens-before 关系
本地逻辑时钟值Ci,Ci (a) 表示进程Pi发生事件a时的逻辑时钟值,Ci的更新算法如下:
- 进程Pi每发生一次事件,Ci加1。
- 进程Pi给进程Pj发送消息,需要带上自己的本地逻辑时钟Ci。
- 进程Pj接收消息,更新Cj为 max (Ci, Cj) + 1。
锁集法
在多线程程序中,使用锁对临界区(临界区中包含一般都是共享变量的访问操作)进行保护,
如果一个共享变量在程序多线程执行过程中能够始终被一个或多个锁保护的话,那么在该共享变量上肯定不会发生数据竞争。反之,则有可能发生数据竞争。
1、Initialization
对于每个线程t,都会维护一个locks_held(t)表明当前获得的锁集
对于每一个共享变量v,这个变量在初始化的时候获得程序执行过程中的所有可能锁集C(v)
2、Refinement
当前线程对该共享变量的每次访问(读/写),更新C(v)=C(v) ∩ locks_held(t)
如果C(v)为{ } ,那么就报告一个警告