如果不使用pthread_join(),为什么'cout'语句从特定线程打印两次(甚至是同步)?

时间:2015-08-10 07:48:04

标签: c++ multithreading pthreads

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

我已经在linux fedora 22(也在http://www.cpp.sh/上)执行了以下程序大约20次,在20次执行中我发现了以下输出: -

输出1:

In main thread  
First thread execution  

输出2:

First thread execution  
In main thread  

输出3:

In main thread  

输出4:

In main thread  
First thread execution  
First thread execution  

预计输出1到3,因为主线程没有等待子线程退出。两个线程(main和child)的执行顺序完全依赖于内核线程调度。

但输出4很奇怪!!! First thread execution被打印两次!!!

现在,如果我在取消注释代码'pthread_join(th1,NULL)'或添加'pthread_exit(NULL)'后运行程序,我就不会得到奇怪的输出(即First thread execution从未打印过两次),甚至我运行代码10000次。

我向专家提出的问题是:

  1. 没有pthread_join / pthread_exit在场景后面发生了什么,以便First thread execution打印了两次?
  2. pthread_join的责任是获取特定线程的退出代码,并且在成功调用pthread_join之后,内核将释放该特定线程的资源。如果我不在可连接线程上调用pthread_join那么它会导致资源泄漏,但为什么上面提到了奇怪的行为?

    我们可能会说,这是未定义的行为,但如果有任何专家就此提供技术解释,那将会很棒。

    1. pthread_join / pthread_exit如何防止上述奇怪行为?由于这种奇怪的行为,它在这里做了什么隐藏的事情?
    2. 感谢提前专家..

2 个答案:

答案 0 :(得分:1)

我在类似情况下观察过这种双面打印。当您的线程在$check = mysql_query("SELECT user_task_types, user_task_types_id FROM dotp_user_task_type WHERE user_id = '$user_id'"); $row = mysql_fetch_array($check); $user_task_types = explode(',',$row[0]); $user_task_types_id = explode(',', $row[1]); $new_array = array(); foreach($user_task_types as $key => $val) { $new_array[$user_task_types_id[$key]] = $val; } 系统调用中等待正常输出时,特别是在此堆栈中:

write

程序正常终止,正常终止导致输出子系统刷新所有缓冲区。 stdin上的输出缓冲区尚未标记为空闲(写入系统调用尚未返回),因此它被再次写出:

#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

在任何情况下,加入你的线程(如果你使用C ++线程,它会提醒你这样做)或以其他方式同步对输出流的访问。

答案 1 :(得分:0)

主线程可能早于生成的线程结束。

结束主线程意味着结束整个过程,同时所有线程突然停止。这可能会调用未定义的行为,因此任何事情都可能发生。

绕过这个

  • 使用pthread_join(),{/ li>中的main()加入衍生线程
  • 或使用pthread_exit()结束主线程,它只是结束主线程并使进程不会结束。