C11中_Atomic的临界区及原子操作与mutex等价性疑问
原子操作与互斥锁等价性疑问
根据cppreference的说明,对于_Atomic类型的变量(比如_Atomic int a),++a、a++、a %= 2这类操作均为原子操作。但我有一个疑问:以下代码中的表达式(thread_counter++) % THREAD_NUM,是否与使用mutex实现的版本具备同等的原子性?
原子变量实现版本
_Atomic size_t thread_counter = 0; void thread_counting() { int execution_id = (thread_counter++) % THREAD_NUM; }
互斥锁实现版本
pthread_mutex_t my_mutex; size_t thread_counter = 0; void thread_counting() { pthread_mutex_lock(&my_mutex); // 假设pthread_mutex_lock()始终成功 int execution_id = (thread_counter++) % THREAD_NUM; pthread_mutex_unlock(&my_mutex); }
由于C11标准的表述较为晦涩,我没能从中得到明确答案。为此我编写了如下测试代码,运行结果似乎表明二者等价,但不确定测试代码是否存在明显缺陷:
#include <pthread.h> #include <stdatomic.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #define THREAD_NUM 5000 #define PASS_NUM 128 _Atomic uint8_t *table = NULL; _Atomic size_t thread_counter = 0; _Atomic short error = 0; void *counting(void *pass) { uint8_t p = *((uint8_t *)pass); if (error) { return NULL; } int execution_id = (thread_counter++) % THREAD_NUM; // 替代实现,会破坏原子性: // thread_counter = (thread_counter + 1) % THREAD_NUM; // int execution_id = thread_counter; if (table[execution_id] == p) { table[execution_id] = p + 1; } else { fprintf(stderr, "ERROR: table[%d]==%u, expecting %u\n", execution_id, table[execution_id], p); ++error; } return NULL; } void test_concurrent_counting() { table = (_Atomic uint8_t *)calloc(THREAD_NUM, sizeof(short)); if (table == NULL) { perror("calloc()"); goto err_calloc_table; } pthread_t *ths = (pthread_t *)calloc(THREAD_NUM, sizeof(pthread_t)); if (table == NULL) { perror("malloc()"); goto err_malloc_pthread; } for (uint8_t i = 0; i < PASS_NUM && error == 0; ++i) { printf("Pass no.%u\n", i); int j = 0; for (; j < THREAD_NUM; ++j) { if (pthread_create(&ths[j], NULL, counting, &i) != 0) { // 该错误处理可能不够完善 --j; perror("pthread_create()"); break; } } for (int k = 0; k <= j; ++k) { (void)pthread_join(ths[k], NULL); } } free(ths); err_malloc_pthread: free(table); err_calloc_table: return; } int main(void) { test_concurrent_counting(); return 0; }
内容的提问来源于stack exchange,提问作者D.J. Elkind
相关产品推荐
相关产品推荐

