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

时间:2015-08-18 15:32:24

标签: c linux multithreading mutex

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

#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;
}

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

  

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

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

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

尝试将add更改为以下内容:

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线程知道如何/何时关闭自己也是一种好习惯。我在这里展示的只是一种方法。

另外,仅供参考,主要的pthread_mutex_destroy()远非保证无论如何都能成功。在锁定或引用互斥锁时(例如通过条件变量),不能销毁互斥锁​​。因此,如果add在尝试销毁时遇到锁定,pthread_mutex_destroy() 应该返回错误。