c++ - 奇怪的线程行为

标签 c++ c multithreading pthreads mutex

下一个代码通常会打印 BA,但有时它会打印 BBAA、BAAB、... 怎么可能得到两个 A 或 B?!然而这段代码从不打印三个 A 或 B。两个函数(生产和消费)都运行很多线程。非常感谢。

int permission;
void set_permission(int v) {
    permission = v;
    printf("%c", v + 'A');fflush(stdin);
}
void* produce(void*) {
    for (;;) {
        pthread_mutex_lock(&mr1);
        set_permission(1);
        while (permission == 1);
        pthread_mutex_unlock(&mr1);
    }
}
void* consume(void*) {
    for (;;) {
        pthread_mutex_lock(&mr2);
        while (permission == 0);
        set_permission(0);
        pthread_mutex_unlock(&mr2);
    }
}

最佳答案

您的线程未同步,因为它们未使用相同的互斥量。

另一个线程偶然只能设法将 permission 设置为 1 或 0,但尚未设法产生输出。在这种情况下,第一个线程似乎运行了两整轮。

当内存内容在内核和两个线程写入之间同步时,相应线程的写入也可能完全丢失。互斥体也可以防止这种情况发生,因为它建立了严格的内存访问顺序,简单来说,保证了在一个互斥体保护下发生的一切对同一互斥体的下一个用户是完全可见的。

打印同一个字符 3 次或更多次的可能性很小,因为中间最多发生一次写入,因此最多一次丢失写入,或者一次乱序输出。但这并不能保证。

如果您在一个根本没有隐式内存同步的系统上工作,您的代码也可能直接死锁,因为在一个互斥体下完成的写入永远不会传播到另一个互斥体的用户。 (实际上并没有发生,因为 IO 操作仍然引入了一些同步。)

关于c++ - 奇怪的线程行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46398068/

相关文章:

c# - 在 .NET 中序列化,在 C++ 中反序列化

c - 为什么我的代码会跳过用户的输入?

java - 如何从java类调用javafx类?

multithreading - "locks are an expensive operation"经常被说出来的原因是什么?

c++ - 如何在用户在运行时输入任何内容时停止计时器

c++ - OpenCV:如何检测特定颜色的线条?

c++ - 将类型隐藏在类中并在内部使用

c - 在 C 中使用 strcat 时程序返回 -1073741819

编译包含包含 C 定义的头文件的汇编代码

c++ - 添加不存在的目标时,强制CMake target_link_libraries失败