☰
  • 首页
  • 规则分类
  • 项目介绍
search
•••

避免在事务中多次非同步地访问原子对象

16.3 ID_atomicRaces
目录 › next › previous

原子对象可以保证某些特定操作的原子性,但特定操作的组合并不具备原子性,非同步地访问原子对象仍然存在数据竞争。

示例:

atomic_int i = ATOMIC_VAR_INIT(0);

void thd() {
    i = i + 1;   // Non-compliant, data races
}

设 thd 为线程函数,原子对象 i 在表达式中出现了多次,其读取、计算、写入等过程在多线程中仍然是交织在一起的,造成数据竞争。

应改为:

void thd() {
    atomic_fetch_add(&i, 1);   // Compliant, or use ‘operator++’ in C++
}

对于一些复杂的原子运算,如:

i = (i + 1) % 5;   // Non-compliant

可采用“CAS(compare and swap)” 方法同步:

int old_i = atomic_load(&i);
int new_i = 0;
do {
    new_i = (old_i + 1) % 5;
} while (!compare_and_swap(&i, &old_i, new_i));   // Compliant

首先读取原子对象的值 old_i,old_i 经过运算得到新值 new_i,再通过 compare_and_swap 更新原子对象的值。compare_and_swap 具有原子性,将 old_i 和原子对象当前值比较,相等则说明在运算过程中原子对象没有被其他线程更新,将原子对象的值设为 new_i,不相等则说明原子对象已被其他线程更新,将 old_i 设为原子对象当前值,再重复这个过程,直到原子对象可用 new_i 更新。

compare_and_swap 是重要的原子对象同步手段,在实际代码中可与 atomic_compare_exchange_weak、atomic_compare_exchange_strong 等函数对应。

相关

ID_dataRaces

参考

SEI CERT CON40-C
Copyright©2024 360 Security Technology Inc., Licensed under the Apache-2.0 license.