You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:35:27