我开始玩线程(pthreads),我不明白如何预测它们是如何工作的。换句话说,我有一个非常简单的程序,它只增加一个变量:
#include <stdio.h>
#include <pthread.h>
int counter = 0;
void *MyThread(void *arg) {
int i;
for (i = 0; i < 10000; i++) {
counter++;
}
return NULL;
}
int main() {
pthread_t tid[40];
int i;
void *val;
void *MyThread(void *);
for (i = 0; i < 40; i++) {
pthread_create(&tid[i], NULL, MyThread, NULL);
}
for (i = 0; i < 40; i++) {
pthread_join(tid[i], &val);
}
printf("Counter = %d\n", counter);
return 0;
}
我不明白为什么它会给出随机结果!如果我创建(并加入)40个线程,为什么他们不能完成所有工作呢?
答案 0 :(得分:2)
增量不是原子操作。因此,如果每个线程同时访问它们,它们可能会破坏计数器值。如果希望多个线程一次访问变量,则必须仅使用原子操作或将操作包装在互斥锁或信号量中。
假设您正在使用gcc,您可以做的最简单的修复是替换行
counter++;
与
__sync_fetch_and_add(&counter, 1);
这将用原子增量替换增量,并希望程序正确执行。
您可以在此处找到有关原子操作的更多信息:http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html
答案 1 :(得分:2)
所有线程都在修改相同的全局变量(计数器)。您应该阅读对此问题的回复
对于POSIX线程,您需要使用互斥锁,并且可以找到有关如何在此http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzahw%2Frzahwe18rx.htm
的示例答案 2 :(得分:1)
他们都完成了他们的工作。但是,由于并发问题,它可能没有反映在counter
中
具体来说,在您的示例中,任何线程都没有定义任何线程看到counter
的更新,因为您没有同步它们。
答案 3 :(得分:1)
您正在使用全局变量&#39; counter&#39;。此变量将独立递增,而不会由您创建的所有线程同步。
您不能让多个线程同时操作共享变量(在您的情况下 - 计数器),并且没有适当的同步机制。否则你会有一个race condition。这会导致不确定的行为。
您应该使用pthread互斥锁来锁定您的代码,这些代码不是原子的并且可以改变共享变量,并且可以由线程独立执行。
编写多线程代码时应注意thread safety。