数据竞争(data race)问题分析的利器——valgrind的Helgrind
Posted breaksoftware
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据竞争(data race)问题分析的利器——valgrind的Helgrind相关的知识,希望对你有一定的参考价值。
数据竞争(data race)是指在非线程安全的情况下,多线程对同一个地址空间进行写操作。一般来说,我们都会通过线程同步方法来保证数据的安全,比如采用互斥量或者读写锁。但是由于某些笔误或者设计的缺陷,还是存在data race的可能性的。(转载请指明出于breaksoftware的csdn博客)
比如下面这段代码
#define _GNU_SOURCE 1
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static pthread_rwlock_t s_rwlock;
static int s_racy;
static void sleep_ms(const int ms)
struct timespec delay = ms / 1000, (ms % 1000) * 1000 * 1000 ;
nanosleep(&delay, 0);
static void* thread_func(void* arg)
pthread_rwlock_rdlock(&s_rwlock);
s_racy++;
pthread_rwlock_unlock(&s_rwlock);
sleep_ms(100);
return 0;
int main(int argc, char** argv)
pthread_t thread1;
pthread_t thread2;
pthread_rwlock_init(&s_rwlock, 0);
pthread_create(&thread1, 0, thread_func, 0);
pthread_create(&thread2, 0, thread_func, 0);
pthread_join(thread1, 0);
pthread_join(thread2, 0);
pthread_rwlock_destroy(&s_rwlock);
fprintf(stderr, "Result: %d\\n", s_racy);
return 0;
线程函数thread_fun主要工作就是对全局变量s_racy进行自增。由于自增是写操作,所以需要加锁。但是第16行加的是读锁——共享锁,这就意味着其他线程也会获得该读锁。这个错误就将导致两个线程同时无协调的修改s_racy变量。
对这个问题,我们可以使用如下指令分析
valgrind --tool=helgrind ./rdlock_race
最后我们会得到如下的结果显示
==5457== Possible data race during write of size 4 at 0x309078 by thread #3
==5457== Locks held: none
==5457== at 0x108A19: thread_func (rwlock_race.c:25)
==5457== by 0x4C36C26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5457== by 0x4E496DA: start_thread (pthread_create.c:463)
==5457== by 0x518288E: clone (clone.S:95)
==5457==
==5457== This conflicts with a previous write of size 4 by thread #2
==5457== Locks held: none
==5457== at 0x108A19: thread_func (rwlock_race.c:25)
==5457== by 0x4C36C26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5457== by 0x4E496DA: start_thread (pthread_create.c:463)
==5457== by 0x518288E: clone (clone.S:95)
==5457== Address 0x309078 is 0 bytes inside data symbol "s_racy"
==5457==
第1行显示线程3访问的0x309078地址有4个字节空间可能存在数据竞争。
第2行显示线程3操作这个空间时没有持有独占锁。其具体操作的调用堆栈在第3到第6行体现。
第8行显示线程2也操作了这个空间。
第9行显示线程2操作这个空间是也没有持有独占锁。
第14行则直接指出被操作的空间的变量名称为s_racy。
如此我们便找到存在数据竞争的变量了。
我们将读锁改成写锁——即将pthread_rwlock_rdlock改成pthread_rwlock_wrlock,就不会出现上述分析结果了。
以上是关于数据竞争(data race)问题分析的利器——valgrind的Helgrind的主要内容,如果未能解决你的问题,请参考以下文章
Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题
coreData executeFetchRequest 方法的 Race Condition 导致 nil 数据的问题