【问题标题】:pthreads in c coming back with unexpected resultsc 中的 pthreads 以意想不到的结果返回
【发布时间】:2014-06-15 13:22:31
【问题描述】:

我正在使用 2 个非同步线程将全局 volatile int 从 0 增加到 10000000。正如预期的那样,int 有时会以 10000001 结束。

但是,我还在计算两个线程使用特定于线程的局部变量执行其增量操作的次数,并且该变量大幅超调。代码如下:

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

volatile int x = 0;


void* incThread(void* x) {
    int* y;
    y = malloc(sizeof(int));
    *y = 0;

    printf("tstart\n");

    while(*((int*)x) < 10000000) {
        *y = *y + 1;
        *((int*)x) = *((int*)x) + 1; 
        if(*y % 1000000 == 0) {
            printf(">thread at %i\n", *y));
        }
    }

    printf("tend\n");

    pthread_exit(y);
}



int main(int argc, char* argv[]) {

    pthread_t thread1;
    pthread_t thread2;

    volatile int* xp;
    xp = &x;

    int* ret1;
    int* ret2;


    printf("\n\n\nTHREAD LAUNCH PROGRAM\n");
    printf("-------------------------------------\n");
    printf("I'll launch two threads.\n");
    printf("Both will try incrementing the global value x to 10000000 before exiting.\n\n");


    pthread_create(&thread1, NULL, incThread, (void*)xp);
    pthread_create(&thread2, NULL, incThread, (void*)xp);
    pthread_join(thread1, (void**) &ret1);
    pthread_join(thread2, (void**) &ret2);


    printf("   Thread01 exited after %i loops.\n", *ret1); 
    printf("   Thread02 exited after %i loops.\n", *ret2);
    printf("                        --------\n");
    printf("                     => %i total\n", ((*ret1)+(*ret2)));
    printf("\n");
    printf("x ended up at %i.\n", x);
    printf("\n");

    return 0;
}

因此,运行它会打印出线程迭代计数器的滑稽结果(incThread() 中的 int y);例如,Thread01 的 y = 5801001 和 Thread02 的 y = 5456675,总计超过预期值 112%,即 10000000。同时,x 本身最终达到 10000000 或更高,正如预期的那样。

什么给了?迭代次数怎么会这么高?

操作系统信息和我认为应该发生的事情: 整个运行的虚拟 debian 7.1 将其关联设置为一个 CPU 内核。 我希望虚拟操作系统在程序进程中打开 3 个线程。然后,由于它作为其常规执行周期的一部分从一个进程迭代地切换到另一个进程,只要它专注于该特定进程,它还应该在每个进程线程(在本例中为主线程和自定义线程 1 和 2)不断切换。

所以,有一个主线程启动 t1 和 t2,然后等待 thread1 完成,一旦完成,它就等待 thread2 完成,然后继续打印结果。但据我了解,这些都不能解释 y 为何会偏离 x 这么多。

【问题讨论】:

    标签: c multithreading concurrency pthreads debian


    【解决方案1】:

    发生这种情况是因为每次 两个 线程的迭代都可能使 x 递增一次。 例如,

    t1:读取 x 值(x 为 5)
    t2:读取 x 值(x 为 5)
    t1:递增并存储 x(x 为 6)
    t2:递增并存储 x(x 为 6)

    所以两个线程都完成了一次迭代,但 x 的值只增加了一次。理论上,您的 EACH 线程最多可以运行 10000000 次。

    【讨论】:

    • +1。您可能想要添加需要防止数据竞争来解决问题(可能使用互斥锁)。
    【解决方案2】:

    这是典型的race conditiony = y + 1 不是原子的,由 3 个操作组成:读取、递增、写入。读操作后可以进行线程切换,其他线程将读取相同的值,递增和写入。然后另一个将继续执行并对相同的值重复相同的操作。所以增量发生了 2 次,但结果只会是一个增量。

    【讨论】:

      【解决方案3】:

      我只是想加强@chickenpie 的答案。以下情况很容易发生:

      t1:读取 x 值(x 为 5)
      t2:读取 x 值(x 为 5)
      t2:递增并存储 x(x 为 6)
      t2:递增并存储 x(x 为 7)
      ... 说 10 次
      t2:递增并存储 x(x 为 17)
      t1:递增并存储 x(x 为 6)

      当第一个线程从一个物理内核切换到另一个物理内核或被中断以执行其他任务时,可能会发生这种情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-07
        • 1970-01-01
        • 2019-04-05
        • 1970-01-01
        • 1970-01-01
        • 2021-06-11
        相关资源
        最近更新 更多