假设我有以下 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 上运行上面的“程序”,扩展到 1000 个线程,100000 次
使用GCC 8.3.0,-std=c99,看起来它们不会互相干扰;
然而,我认为这样的实验不足以得出这样的访问是
在所有平台上线程安全。
编辑1:
这个问题是关于访问不同的 different 元素
线程,不同线程中不能有相同的元素;那是,
例如,
thread-1
读取/写入 arr[1]
而 thread-2
读取/写入 arr[2]
。
如果你能保证在同一时刻每个元素只能被一个线程访问,那么它就是线程安全的。因为数组的每个元素都彼此不同(物理上),这意味着它们是内存的独立部分。
[已编辑]
在 C 中访问数组的不同元素是完全线程安全的。
访问不同元素始终是 100% 安全的。
这个问题问得好。如果CPU的基本操作在32位内存上进行,那么在线程1中CPU将读取32位,更新左边的16位,然后写回32位。这将覆盖右侧的 16,该值可能已被线程 2 在线程 1 读取和写入之间更改。然而,我们希望原始问题的作者不是第一个想到这一点的人,并且在现实世界中,编译器编写者会采取步骤来发出正确的代码。最简单的方法是在 32 位边界上对齐数组元素,即使大小为 16。