当前位置: 首页 > 知识库问答 >
问题:

使用互斥锁时,printf输出两次(或更多?我不确定)?

涂泰平
2023-03-14

我正在学习线程同步。我的测试代码如下:

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

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int count = 0;
void* add(void * params)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        fprintf(stdout, "thread:%ld, count:%d\n",pthread_self(), count);
        count++;
        pthread_mutex_unlock(&mutex);
    }
    return 0;
}

void* print(void * params)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        if (count > 100)
        {
            printf("count greater than 100,count: %d\n", count);
            pthread_mutex_unlock(&mutex);
            break;
        }
        pthread_mutex_unlock(&mutex);
    }
    return 0;
}

int main(void)
{
    pthread_t thread1, thread2, thread3;
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&thread1, NULL, add, NULL);
    pthread_create(&thread2, NULL, add, NULL);
    pthread_create(&thread3, NULL, print, NULL);
    pthread_join(thread3, NULL);
    pthread_mutex_destroy(&mutex);

    return 0;
}

我以为“计数”的每一个输出都会连续增加一个。然而,事实却大不相同。就像:

//程序输出开始:线程:139663694870272,计数:0线程:139663694870272,计数:1线程:139663694870272,计数:2线程:139663694870272,计数:3线程:139663694870272,计数:4线程:139663694870272,计数:5线程:139663686477568,计数:6线程:139663686477568,计数:7线程:139663686477568,计数:8线程:139663686477568,计数:9线程:,计数:11线程:139663686477568,计数:12线程:139663686477568,计数:13线程:139663686477568,计数:14线程:139663686477568,计数:15线程:139663686477568,计数:16线程:139663686477568,计数:17线程:139663686477568,计数:18线程:139663686477568,计数:19线程:139663686477568,计数:20线程:139663686477568,计数:21线程:139663686477568,计数:22(某些行被忽略)线程:139663686477568,计数:172计数大于100,计数:173线程:139663686477568,计数:173线程:139663686477568,计数:174线程:139663686477568,计数:175线程:139663686477568,计数:176线程:139663686477568,计数:177线程:139663686477568,计数:178线程:139663686477568,计数:179线程:139663686477568,计数:180线程:139663686477568,计数:181线程:139663686477568,计数:182线程:139663686477568,计数:183线程:139663686477568,计数:184线程:139663686477568,计数:185线程:139663686477568,计数:186线程:139663686477568,计数:187线程:139663686477568,计数:188线程:139663686477568,计数:189线程:139663686477568,计数:190线程:1396686477568,计数:191线程:139663686477568,计数:192线程:139663686477568,计数:193线程:139663686477568,计数:194线程:139663686477568,计数:195线程:139663686477568,计数:196线程:139663686477568,计数:197线程:139663686477568,计数:198线程:139663686477568,计数:199线程:139663686477568,计数:200线程:139663686477568,计数,计数:202线程:139663686477568,计数:203线程:139663686477568,计数:204线程:139663686477568,计数:205线程:139663686477568,计数:206线程:139663686477568,计数:206线程:139663686477568,计数:207线程:139663686477568,计数:208线程:139663686477568,计数:209线程:139663686477568

我不知道“printf”在这种情况下做什么?为什么它会输出两次。

共有2个答案

郭洋
2023-03-14

大卫有正确的答案...在所有线程都退出之前不要破坏互斥锁。我只是想稍微扩展一下,因为你似乎只是在学习pthread。

尝试更改添加,如下所示:

void* add(void * params)
{
    int quit =0;
    while(!quit)
    {
        if( 0 == pthread_mutex_lock(&mutex) )
        {
           fprintf(stdout, "thread:%ld, count:%d\n",pthread_self(), count);
           count++;
           if( count > 100 ) quit = 1;
           pthread_mutex_unlock(&mutex);
        }
        else
        {
           fprintf(stderr, "Failed to lock mutex.  Exiting.\n");
           quit=1;
        }
    }
    return 0;
}

有两大变化:

>

  • 检查pthread_mutex_lock的返回值。总是这样。您可以检查返回值,看看为什么失败,但通常如果锁定失败,您不想访问受锁保护的资源。

    add线程知道如何/何时关闭自己也是一种很好的做法。我在这里展示的只是一种方法。

    另外,仅供参考,main中的pthread_mutex_destroy()远远不能保证成功。当互斥锁被锁定或引用时(例如,通过条件变量),不能销毁互斥锁。因此,如果add在尝试销毁它时拥有锁,pthread_mutex_destroy()应该会返回一个错误。

  • 范承望
    2023-03-14

    一旦互斥锁被销毁,所有赌注都将被取消。在确定没有线程可以使用互斥锁之前,不应该销毁互斥锁。

     类似资料:
    • 问题内容: 我从python中的多线程开始(或者至少我的脚本有可能创建多个线程)。该算法是否是Mutex的正确用法?我尚未测试此代码,它可能甚至无法正常工作。我只希望processData在一个线程中运行(一次一个),而主while循环保持运行,即使队列中有一个线程也是如此。 编辑:重新阅读我的代码,我可以看到它是完全错误的。但是,这就是为什么我在这里寻求帮助。 问题答案: 我不知道您为什么要使用

    • Go语言包中的 sync 包提供了两种锁类型:sync.Mutex 和 sync.RWMutex。 Mutex 是最简单的一种锁类型,同时也比较暴力,当一个 goroutine 获得了 Mutex 后,其他 goroutine 就只能乖乖等到这个 goroutine 释放该 Mutex。 RWMutex 相对友好些,是经典的单写多读模型。在读锁占用的情况下,会阻止写,但不阻止读,也就是多个 gor

    • Introduction This is the fourth part of the chapter which describes synchronization primitives in the Linux kernel and in the previous parts we finished to consider different types spinlocks and semap

    • 问题内容: 帮助客户解决他们遇到的问题。我更多地是sysadmin / DBA的人,所以我在努力帮助他们。他们说这是内核/环境中的错误,在我坚持要在他们的代码中或寻求供应商对OS的支持之前,我试图证明或证明这一点。 发生在Red Hat和Oracle Enterprise Linux 5.7(和5.8)上,应用程序用C ++编写 他们遇到的问题是主线程启动一个单独的线程来执行可能长时间运行的TCP

    • 我不明白的是,当condition_variable和互斥体之间没有任何链接的时候,为什么所有4个线程都可以在互斥体上获得锁?

    • 我已经编写了3个互斥类TMutex、TCondition和TSpinLock,它们都有一个void lock()和一个void unlock()成员。现在我想对它们使用std::lock\u-guard。我在源文件末尾为我的新互斥类安装了lock_guard,如下所示: 如果我使用: 我收到以下编译器错误消息: .../src/inc/threads.cpp:317: 39:错误:没有匹配函数调用