pthread:一个printf语句在子线程中打印两次

时间:2012-11-25 11:40:36

标签: pthreads printf

这是我的第一个pthread程序,我不知道为什么printf语句在子线程中打印两次:

int x = 1;

void *func(void *p)
{
    x = x + 1;
    printf("tid %ld: x is %d\n", pthread_self(), x);
    return NULL;
}

int main(void)
{
    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);

    printf("main thread: %ld\n", pthread_self());

    func(NULL);
}

在我的平台上观察到的输出(Linux 3.2.0-32-generic#51-Ubuntu SMP x86_64 GNU / Linux):

1.
main thread: 140144423188224
tid 140144423188224: x is 2

2.
main thread: 140144423188224
tid 140144423188224: x is 3

3.
main thread: 139716926285568
tid 139716926285568: x is 2
tid 139716918028032: x is 3
tid 139716918028032: x is 3

4.
main thread: 139923881056000
tid 139923881056000: x is 3
tid 139923872798464tid 139923872798464: x is 2

表示3,来自子线程的两个输出行

为4,与3相同,甚至输出也是交错的。

3 个答案:

答案 0 :(得分:3)

看起来真正的答案是Michael Burr的评论引用了这个glibc错误:https://sourceware.org/bugzilla/show_bug.cgi?id=14697

总之,glibc在程序退出时没有正确处理stdio缓冲区。

答案 1 :(得分:2)

线程通常通过时分复用发生。处理器在两个线程之间均匀切换通常是无效的,因为这需要更多的努力和更高的上下文切换。通常你会发现一个线程在切换之前会执行几次(如例3和4的情况)。子线程在最终终止之前执行多次(因为主线程退出)。

  

示例2:我不知道为什么在没有输出时子线程增加了x。

考虑一下。主线程执行。它调用pthread并创建一个新线程。新的子线程增加x。在子线程能够完成printf语句之前,主线程启动。突然它也增加x。但是主线程也能够运行printf语句。突然x现在等于3。 主线程现在终止(也导致子3退出)。 这可能是你的情况下发生的例子2。

示例3清楚地表明变量x由于低效的锁定和堆栈数据损坏而被破坏!!

有关线程的更多信息。

Link 1 - Additional info about threading

Link 2 - Additional info about threading

您还会发现,因为您正在使用x的全局变量,所以在线程之间共享对此变量的访问。这很糟糕。非常非常糟糕,因为访问相同变量的线程会因为在变量x的同一寄存器上发生多次读写而导致竞争条件和数据损坏。 正是由于这个原因,使用了互斥体,它实际上创建了一个锁,同时更新变量以防止多个线程同时尝试修改同一个变量。 互斥锁将确保x按顺序更新,而不是像你的情况那样偶尔更新。

有关Pthreads in General和Mutex锁定示例的更多信息,请参阅此链接。
Pthreads and Mutex variables

干杯,
彼得

答案 2 :(得分:2)

嗯。您的示例使用来自不同线程的相同“资源”。一个资源是变量x,另一个是stdout文件。所以你应该使用如下所示的互斥锁。最后,pthread_join等待另一个线程完成其工作。 (通常一个好主意也是检查所有这些pthread ...调用的返回码)

#include <pthread.h>
#include <stdio.h>
int x = 1;
pthread_mutex_t mutex;

void *func(void *p)
{
    pthread_mutex_lock (&mutex);
    x = x + 1;
    printf("tid %ld: x is %d\n", pthread_self(), x);
    pthread_mutex_unlock (&mutex);
    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, 0);

    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);

    pthread_mutex_lock (&mutex);
    printf("main thread:  %ld\n", pthread_self());
    pthread_mutex_unlock (&mutex);

    func(NULL);
    pthread_join (tid, 0);
}