pthread:一个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和例子4)。子线程在终止之前执行了多次(因为主线程已经退出)。

例2:我不知道为什么x在没有输出的情况下被子线程增加。

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

例3清楚地表明variablesx由于低效的locking和堆栈数据损坏而被破坏了!

有关线程是什么的更多信息。

链接1 – 有关线程的其他信息

链接2 – 有关线程的其他信息

另外你会发现,因为你正在使用x的全局variables,访问这个variables是在这个线程之间共享的。 这是坏的..非常非常糟糕的线程访问相同的variables创build竞争条件和数据损坏由于多个读写发生在同一个variablesx寄存器。 正是因为这个原因,使用了互斥体,它们本质上是在variables被更新时创build一个锁,以防止多个线程同时尝试修改相同的variables。 互斥锁将确保x按顺序更新,而不是像你的情况那样零星地。

请参阅此链接了解更多关于常规和互斥locking示例中的Pthreads的信息。
Pthreads和Mutexvariables

干杯,
彼得

嗯。 你的例子使用来自不同线程的相同“资源”。 一个资源是variablesx,另一个是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); } 

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

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