使用线程的意外结果

时间:2014-04-20 18:19:00

标签: c pthreads

我开始玩线程(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个线程,为什么他们不能完成所有工作呢?

4 个答案:

答案 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)

所有线程都在修改相同的全局变量(计数器)。您应该阅读对此问题的回复

Global variables and threads

对于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