pthread互斥锁未正常工作

5

我目前正在学习麻省理工学院的开放式课程,名为《实用C语言编程》。在讨论多线程中的竞态条件时,讲义中包含了一个存在竞态条件的程序示例,并展示了如何使用互斥锁来解决该问题。该代码在Linux系统上按预期运行,但在OS X上则不然。

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

pthread_mutex_t mutex; // Added to fix race condition
unsigned int cnt = 0;

void *count(void *arg) {
    int i;
    for (i = 0; i < 100000000; i++) {
        pthread_mutex_lock(&mutex); // Added to fix race condition
        cnt++;
        pthread_mutex_unlock(&mutex); // Added to fix race condition
    }
    return NULL;
}

int main() {
    pthread_t tids[4];
    int i;
    for (i = 0; i < 4; i++)
        pthread_create(&tids[i], NULL, count, NULL);
    for (i = 0; i < 4; i++)
        pthread_join(tids[i], NULL);
    pthread_mutex_destroy(&mutex); // Added to fix race condition
    printf("cnt = %u\n", cnt);
    return 0;
}

在添加互斥锁和相应的函数调用之前,行为与预期相符,对于cnt(400000000)产生理论上正确响应的变量分数在每次运行时都不同。添加了互斥锁后,这种情况仍然存在,尽管结果明显增加,表明它具有某些预期效果,但远非完美。
我尝试在其他3台计算机/虚拟机上编译此程序:一台运行OS X 10.10(第一台运行10.11),一台带有Kali Linux(本质上是Debian Jessie),一台运行Ubuntu。两个OS X运行都显示了与描述相同的奇怪行为。然而,两个Linux系统按预期产生了完美的400000000。
所以我的问题是,为什么在OS X上互斥锁没有按预期工作?
2个回答

9

您没有初始化互斥锁。您可以通过以下两种方式进行初始化:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

或者在 main 函数中执行以下操作:

if ( pthread_mutex_init( &mutex, NULL) != 0 )
    printf( "mutex init failed\n" );

4
在 Linux 下它能够运行的原因是:Linux系统下存在以下情况:
#define PTHREAD_MUTEX_INITIALIZER { { 0, 0, 0, 0, 0, { 0 } } }

这正是互斥锁的初始化方式,因为它是一种.bss变量。

在MacOSX下,它是另一种神奇的值:

#define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
#define _PTHREAD_MUTEX_SIG_init     0x32AAABA7

因此,它确实必须被初始化才能正常工作。


我注意到头文件中的差异,想知道这种差异是否有任何意义。然而,看起来奇怪的问题是,在Linux上没有初始化它,只是声明它,就能得到正确的结果。 - saltthehash
2
@psytech140,我之前已经尝试解释过了:pthread_mutex_t mutex被初始化为零(所有全局c变量都是如此)。这与Linux平台上PTHREAD_MUTEX_INITIALIZER的定义相匹配,但在MacOSX上则不然。 - Ctx
@saltthehash 你说的“给出了正确结果”是什么意思?使用未初始化的互斥锁,什么是“正确的结果”?我不知道。你知道吗? - David Schwartz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接