c - 适用于 Windows 的 Linux 子系统中的线程差异

标签 c multithreading ubuntu pthreads windows-10

与其说是编程问题,不如说是我正在寻求澄清的怪事。考虑以下 C 程序:

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

volatile int counter = 0;

void incrementCounter()
{
    counter += 1;
}

void* threadfunc()
{
    for (int i = 0; i < 1000; i++)
    {
        incrementCounter();
    }
}

int main()
{
    pthread_t tids[100];
    printf("Creating Threads...\n");
    for (int i = 0; i < 100; i++)
    {
        pthread_create(&tids[i], NULL, threadfunc, NULL);
    }

    printf("Joining Threads...\n");

    for (int i = 0; i < 100; i++)
    {
        pthread_join(tids[i], NULL);
    }

    printf("Finished. Counter = %d\n", counter);
}

这是我为大学作业写的。它应该显示在写入变量时多线程未锁定的危险。

我在 Windows 10 上,所以我打开我安装的 Ubuntu Bash,然后运行

$ gcc -std=c99 -pthread main.c
$ ./a.out

打印

Creating Threads...
Joining threads...
Finished. Counter = 100000

好吧……没错。它不应该是正确的。这应该是坏了!

我一次又一次地运行它,结果都是一样的。 Counter = 100000 每一次!这可能是我一生中唯一一次对我的代码无法正常工作感到失望。

所以我登录到我的学校为 CS 学生共享的 Linux 系统。提取我的代码,以相同的方式执行它,我得到:

Creating Threads...
Joining threads...
Finished. Counter = 99234

下一次,Counter = 99900,然后是 Counter = 100000,然后是 Counter = 99082

这就是我所期待的!

所以我的问题:

什么给了?适用于 Windows 的 Linux 子系统有什么原因使我的代码不会中断?

最佳答案

还是坏了。它恰好起作用了。您没有保证代码将正确运行或不正确。您[仍然]在线程之间存在竞争条件

在这里,我使用了两个线程:A 和 B。但是,该示例适用于更多线程。

在 Linux 上,你有:

thread A        thread B
-------------   --------------
fetch
                fetch
inc
                inc
store
                store

在这里,线程 B 的存储将丢弃线程 A 的增量和存储。也就是说,如果原始值为 5,您将得到 6 而不是 [期望的] 7。

在 Windows 下,你得到:

thread A        thread B
-------------   --------------
fetch
inc
store
                fetch
                inc
                store

但是,区别仅在于操作系统调度程序及其策略。没有锁定,就没有保证。

在 Windows 下,它在线程 B 启动并运行之前启动了线程 A,该线程一直运行到完成,因此您会得到“不相交”的行为。

尝试使用更多 [或更少] 的线程数和更大的线程循环值,您应该会看到一些不同的行为

关于c - 适用于 Windows 的 Linux 子系统中的线程差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45764860/

相关文章:

python - 如何使用 "for"循环进行多线程?

c++ - 将 char[N] 参数传递给线程

python - 等待线程完成使用连接。很基本

c - C编程中的定点算法

c - 读取引脚电平 Raspberry Pi

c - difftime 在 MinGW 中返回不正确的值

python - 如何处理 ImportError : cannot import name 'pytree' from 'jaxlib' of using jax?

ubuntu - 无法在 Docker 中重新加载或启动 AppArmor

apache - 是否需要停止 Apache 才能编辑 "/etc/apache2/sites-available/default"?

c - 如何在二维数组中使用 memset 函数来初始化 C 中的成员?