在C语言中,访问数组不同元素是否线程安全?

4
如果我有以下的 C 代码:
int my_global_arr[100];

更普遍地说,
some_type *my_global_arr = malloc(some_size * sizeof(some_type);

在多个线程中同时访问(读写)不同元素是否安全?
例如,如果我有以下内容:

void *my_thread(void *index){
    int idx = *((int *)(index));
    my_global_arr[idx] = idx;
    return NULL;
}

main() 函数中

int a = 1;
int b = 2;
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, my_thread, &a);
pthread_create(&thread2, NULL, my_thread, &b);

pthread_join(thread1, NULL);
pthread_join(thread2, NULL);

这两个线程之间是否有保证不会互相干扰?

我的实验结果:
我试图在 x86_64 CPU 上使用 GCC 8.3.0 和 -std=c99 编译选项,将上述“程序”扩展到1000个线程,重复运行100000次,并且看起来它们不会互相干扰; 然而,我认为这样的实验并不足以得出在所有平台上都是线程安全的结论。

编辑1:
这个问题是关于在不同的线程中访问不同的元素,而不是在不同的线程中访问同一个元素;也就是说, 例如线程 1 读取/写入 arr[1],而线程 2 读取/写入 arr[2]


1
如果您不修改其他线程访问的相同元素,则是100%安全的。 - 0___________
@P__J__并不认为这对所有架构和所有类型都是正确的。 - Martin James
3个回答

3

[编辑]

在C语言中访问不同元素的数组是完全线程安全的。


这个答案本身似乎是完全正确的,但我认为我的问题是关于访问不同索引元素的,正如问题中第5行所述。 - user12986714
哦,我误读了问题。我会编辑我的回答 :) - Abhijeet Kale
我并不确信在仅允许多字节访问的架构上,例如一次32个字节,对数组相邻字节的访问是安全可靠的。因此,如果需要读取、布尔运算和写入来访问小于32位的类型,则可能存在风险。 - Martin James

3

如果你能保证在同一时间只有一个线程访问每个元素,那么它就是线程安全的。因为数组的每个元素都不同(物理上),这意味着它们是分离的内存部分。


2
在一般情况下,对于比int类型更小或不是int类型的精确倍数的压缩类型,会怎样处理呢?这些类型可能需要通过读取/布尔操作/写入序列进行访问,例如,在只允许32位读取/写入的系统上,需要对字节进行操作。 - Martin James
@MartinJames 我认为在你所解释的情况下,不可能同时被两个线程访问。 - SpongeBob
1
为什么不呢?线程A通过布尔掩码等方式读取和修改寄存器中的一个字节,被中断。线程B读取并修改相邻的一个字节,通过掩码修改其字节,并写入。稍后,线程A覆盖了线程B所做的更改: - Martin James

1

访问不同元素将始终是100%安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接