Why is the "cout" expression printed twice (even synchronized) from a specific thread if pthread_join () is not used?
#include < iostream >
#include < pthread.h >
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* Func(void *)
{
pthread_mutex_lock(&mutex);
cout << "First thread execution" << endl;
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t th1;
pthread_create(&th1, NULL, Func, NULL);
pthread_mutex_lock(&mutex);
cout << "In main thread" << endl;
pthread_mutex_lock(&mutex);
// pthread_join(th1, NULL); // Note this code is commented
return 0;
}
I have run the following program on linux fedora 22 (also at http://www.cpp.sh/ ) about 20 times and out of 20 I have done I found the following outputs: -
Output1:
In main thread
First thread execution
Output2:
First thread execution
In main thread
output3:
In main thread
Output4:
In main thread
First thread execution
First thread execution
Exits 1 through 3 are expected because the main thread is not waiting for the child thread to exit. The sequence of execution of both threads (main and child) depends entirely on the scheduling of the kernel threads.
But exit 4 is strange !!! First thread execution
is printed twice !!!
Now if I run the program after the code without commenting out 'pthread_join (th1, NULL)' or added 'pthread_exit (NULL)' I don't get weird output (i.e. First thread execution
never printed twice) ever, even I run the code 10,000 times.
My questions for experts:
- Without pthread_join / pthread_exit, what's going on behind the scenes to get
First thread execution
printed 2 times?
Pthread_join's answer is to get the exit code for a specific thread, and upon a successful call to pthread_join, the kernel will release the resources of that specific thread. If I don't call pthread_join on the thread being connected it will leak resources, but why is the above mentioned strange behavior
It can be said that this is undefined behavior, but it would be great if some expert could provide a technical explanation for this.
- How can pthread_join / pthread_exit prevent the above strange behavior? What hidden thing he's doing here because of this strange behavior doesn't show up?
Thanks to the experts in advance.
source to share
I have seen similar double printing in a similar situation. While your thread was waiting in a system call write
, executing its normal output, specifically on this stack:
#0 0x00007ffff78f4640 in write () from /lib64/libc.so.6
#1 0x00007ffff788fb93 in _IO_file_write () from /lib64/libc.so.6
#2 0x00007ffff788fa72 in new_do_write () from /lib64/libc.so.6
#3 0x00007ffff7890e05 in _IO_do_write () from /lib64/libc.so.6
#4 0x00007ffff789114f in _IO_file_overflow () from /lib64/libc.so.6
the program aborted normally, and a normal termination caused the egress subsystem to flush all buffers. The output buffer on stdin was not marked free yet (the write system call has not returned yet), so it was written out again:
#0 0x00007ffff78f4640 in write () from /lib64/libc.so.6
#1 0x00007ffff788fb93 in _IO_file_write () from /lib64/libc.so.6
#2 0x00007ffff788fa72 in new_do_write () from /lib64/libc.so.6
#3 0x00007ffff7890e05 in _IO_do_write () from /lib64/libc.so.6
#4 0x00007ffff7890140 in _IO_file_sync () from /lib64/libc.so.6
#5 0x00007ffff7891f56 in _IO_default_setbuf () from /lib64/libc.so.6
#6 0x00007ffff7890179 in _IO_file_setbuf () from /lib64/libc.so.6
#7 0x00007ffff7892703 in _IO_cleanup () from /lib64/libc.so.6
#8 0x00007ffff78512f8 in __run_exit_handlers () from /lib64/libc.so.
Either way, join your streams (if you were using C ++ streams, this reminds you of that) or otherwise synchronize access to the output stream.
source to share
The main thread can end earlier than the spawned thread.
Terminating the main thread means terminating the entire process as well as bringing all threads down. This can cause undefined behavior, so anything can happen.
To get around this
- either join the spawned stream using
pthread_join()
frommain()
, - or terminate the main thread using
pthread_exit()
which simply ends the main thread and prevents the process from ending.
source to share