c - 对称多处理系统的输出

标签 c multithreading multiprocessing race-condition

考虑这段代码:

int x; //declared globally

for( int i=0; i<1000000; i++)
           x++;

printf("%d",x);

这是程序的核心逻辑,忽略创建线程等句法的东西

现在,我创建了两个线程,并且程序在运行时表现出竞争条件(很明显!)。

为简单起见,我们假设整个 for 循环针对一个线程一次运行,并且仅在此之后运行第二个线程(假设一个单处理器系统)。因此,第一个线程的理想预期输出为 100 万,第二个问题为 200 万。 (虽然哪个线程打印200万取决于CPU调度器)

我的第一个问题:根据race condition的定义,我每次运行程序时第一个输出和第二个输出都是乱码的,是否可以认为是race condition?为什么?

第二个问题:考虑一个多处理系统,它在两个线程中同时运行 for 循环 100 万次。理想的预期输出是什么?为什么?

最佳答案

我将提供一些示例代码来演示所描述的场景,但由于循环结束和 printf 打印之间的时间差,我将消除差异。我将为此使用一个临时局部变量。

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

pthread_mutex_t x_mutex = PTHREAD_MUTEX_INITIALIZER;
int x = 0;

void *
task_function(void *ptr)
{
    int index;
    int last = 0;

    for (index = 0; index < 1000000; index++) {
        pthread_mutex_lock(&x_mutex);
        last = ++x;
        pthread_mutex_unlock(&x_mutex);
    }

    /* Use last since it won't matter how much time elapses
     * after the loop ends and when the printf is done */
    printf("x = %d\n", last);

}

int
main()
{
    pthread_t thread1, thread2;
    int retval1, retval2;

    /* Create two independent threads which will each execute task_function */
    retval1 = pthread_create(&thread1, NULL, task_function, NULL);
    retval2 = pthread_create(&thread2, NULL, task_function, NULL);

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

如果您运行此代码,最后一个要完成的线程应始终打印 2,000,000 。如果没有,则存在严重错误。然而,第一个完成的将打印一个真正不确定的值,除非您确切知道调度程序如何划分任务以及每个线程的运行速度。

把重点带回家。假设循环是 5 而不是 1000000。假设线程以相同的速度同时运行并且每个增量都是交错的。所以线程 0 首先递增,然后将 x 递增到 1。线程 2 递增,现在是 2。最终,如果此模式重复,线程 1 将首先执行其循环 5 次,并且它将看到值 9。然后线程 2 将完成它并显示 10 的值。正如您所看到的,根据事情的安排方式,如果工作平均分配,理论上这两个值可能会接近。所以在这个例子中,不是打印 510,而是打印 910

如果没有与 x 相关的适当的互斥体/关键部分/原子操作,代码甚至可能不会显示 2000000。这是因为来自两个线程的 x 的更新可能会破坏一个另一个生成不正确的 x 值。如果去掉 task_function 中的互斥量,您可能会发现结果非常古怪。

关于c - 对称多处理系统的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26071303/

相关文章:

c - 减少 C 中套接字之间的时间传输

c - 在 Centos 6.2 上编译 GnuTLS 时出错

java - 线程中出现异常 "main"java.lang.OutOfMemoryError : unable to create new native thread

检查某个 USB 闪存是否连接到我的系统

c++ - 从套接字和 STDIN 提升 Asio 多线程

java - 等待 Fork 加入池 (Java)

ruby - JRuby 多核处理用法

python - 如何使用初始化程序来设置我的多进程池?

python - 这是 python 客户端的有效 TCP/IP 套接字循环吗?

C 中字节序之间的转换