pthread: one printf statement get printed twice in child thread

匿名 (未验证) 提交于 2019-12-03 02:08:02

问题:

this is my first pthread program, and I have no idea why the printf statement get printed twice in child thread:

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

Observed output on my platform (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 

for 3, two output lines from the child thread

for 4, the same as 3, and even the outputs are interleaved.

回答1:

It looks like the real answer is Michael Burr's comment which references this glibc bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14697

In summary, glibc does not handle the stdio buffers correctly during program exit.



回答2:

Threading generally occurs by time-division multiplexing. It is generally in-efficient for the processor to switch evenly between two threads, as this requires more effort and higher context switching. Typically what you'll find is a thread will execute several times before switching (as is the case with examples 3 and 4. The child thread executes more than once before it is finally terminated (because the main thread exited).

Example 2: I don't know why x is increased by the child thread while there is no output.

Consider this. Main thread executes. it calls the pthread and a new thread is created.The new child thread increments x. Before the child thread is able to complete the printf statement the main thread kicks in. All of a sudden it also increments x. The main thread is however also able to run the printf statement. Suddenly x is now equal to 3. The main thread now terminates (also causing the child 3 to exit). This is likely what happened in your case for example 2.

Examples 3 clearly shows that the variable x has been corrupted due to inefficient locking and stack data corruption!!

For more info on what a thread is.

Link 1 - Additional info about threading

Link 2 - Additional info about threading

Also what you'll find is that because you are using the global variable of x, access to this variable is shared amongst the threads. This is bad.. VERY VERY bad as threads accessing the same variable create race conditions and data corruption due to multiple read writes occurring on the same register for the variable x. It is for this reason that mutexes are used which essentially create a lock whilst variables are being updated to prevent multiple threads attempting to modify the same variable at the same time. Mutex locks will ensure that x is updated sequentially and not sporadically as in your case.

See this link for more about Pthreads in General and Mutex locking examples.
Pthreads and Mutex variables

Cheers,
Peter



回答3:

Hmm. your example uses the same "resources" from different threads. One resource is the variable x, the other one is the stdout-file. So you should use mutexes as shown down here. Also a pthread_join at the end waits for the other thread to finish its job. (Usually a good idea would also be to check the return-codes of all these pthread... calls)

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!