Skip to content

Data Races

Introduction

Data Race是指在多线程程序中,两个或多个线程同时访问同一个共享变量,且至少有一个线程是写操作。

Data Race并不是某个编程语言的特性,而是Concurrent Execution的特性。

在数据库中也会出现数据竞争的问题,比如两个事务同时对同一个数据进行操作。解决办法是使用Transaction(事务)。

SQL
1
2
3
4
5
6
7
8
BEGIN TRANSACTION;
SELECT @balance = balance FROM accounts WHERE account_id = 12345;
UPDATE accounts SET balance = @balance - 100 WHERE account_id = 12345;
COMMIT TRANSACTION;
BEGIN TRANSACTION;
SELECT @balance = balance FROM accounts WHERE account_id = 12345;
UPDATE accounts SET balance = @balance - 100 WHERE account_id = 12345;
COMMIT TRANSACTION;

数据竞争很常见,但只出现在并行模型中,如多线程、分布式系统等。

数据竞争可能导致内存问题,假设p是一个被初始化为NULL的全局指针,那么下面的代码可能会导致错误:

C
void thread1() {
    if(!p) {
        p = malloc(128);
    }
    if(p) {
        free(p);
        p = NULL;
    }
}
void thread2() {
    if(!p) {
        p = malloc(256);
    }
    if(p) {
        free(p);
        p = NULL;
    }
}

执行这段代码的可能结果是:两边前后分配了不同大小的内存,但后续释放时却只释放了一次,导致内存泄漏;两边同时释放了同一块内存,导致double free;一边已经置空了p,另一边却又释放了p指向的内存,触发未定义行为。

并行程序中的数据竞争问题很难调试,重复运行可能会得到不同的结果。

Intuitive Definition

Data Race以下情况发生:

  1. 存在不同线程的内存访问操作
  2. 对同一内存位置的访问
  3. 至少有一个是写操作
  4. 两个访问可以自由交错