Linux线程JOINABLE与DETACHED的区别

目录

  • Linux下两种类型线程的创建
    • joinable属性的线程
    • detached属性的线程
    • 代码示例

Linux下两种类型线程的创建

Linux下多线程编程时,线程有两种属性,一种是joinable,一种是detached。

joinable属性的线程

如果是joinable的线程,那么必须使用pthread_join()来等待线程结束,否则线程所占用的资源不会得到释放,会造成资源泄露。
其他线程或父线程如果没有调用pthread_join去做相关资源的释放(pthread id等),该线程运行结束后资源就得不到释放,所在进程的pthread id数目就可能会累积到达最大数目PTHREAD_THREADS_MAX,此时该进程就不能再创建线程了,因为pthread id等资源被用光了,这是在多线程编程中很常见的bug之一。
一个joinable线程,只能有一个pthread_join()来等待结束,如果有多个,则只有第一个执行到的有效,其他的都会直接返回,具体错误信息由pthread_join()函数的返回值返回。
pthread_create()函数默认创建的线程是joinable属性的,或者也可以使用下述代码显示的将线程设为joinable属性:

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&tid, &attr, callback, (void *)context);

detached属性的线程

如果想创建一个线程,但又不想使用pthread_join()等待该线程结束,那么可以创建一个detached的线程。detached属性的线程,在结束的时候,会自动释放该线程所占用的资源。
detached不需要,也不能使用pthread_join()来等待线程结束。
可以用如下代码在来设置并创建detached线程:

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, callback, (void *)context);

代码示例

包含两种属性线程的代码示例:

#include  
#include  
#include  
#include  
#include  

pthread_t       pid_joinable; 
pthread_t       pid_detached; 
 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
 
int             count; 
 
void printids(const char *s) 
{ 
    pid_t       pid; 
    pthread_t   tid; 
 
    pid = getpid(); 
    tid = pthread_self(); 
 
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid, 
        (unsigned int)tid, (unsigned int)tid); 
} 
 
 
void *cb_joinable(void *arg) 
{ 
    printids("New thread joinable begin"); 
 
    printids("New thread joinable:"); 
 
    int i=0; 
    for ( ; i<5; ++i)     
    { 
    	pthread_mutex_lock(&mutex); 
        printf("joinable runing %d\n", count++); 
	    pthread_mutex_unlock(&mutex); 
        sleep(1);
    }
 
    return ((void*)123); 
} 
 
void *cb_detached(void *arg) 
{ 
    printids("New thread detached begin"); 
 
    printids("New thread detached:"); 
 
    int i=0; 
    for ( ; i<10; ++i)     
    { 
 
    	pthread_mutex_lock(&mutex); 
        printf("detached runing %d\n", count++); 
    	pthread_mutex_unlock(&mutex); 
        sleep(1); 
    } 
 
    return ((void*)456); 
} 
 
int main(void) 
{ 
    int err; 
 
    count = 0; 
    pthread_mutex_init(&mutex, NULL); 
 
    err = pthread_create(&pid_joinable, NULL, cb_joinable, NULL); 
    if ( 0 != err ) 
    { 
        printf("can't create joinable thread: %s\n", strerror(err)); 
    } 
 
    pthread_attr_t attr;     
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);    
    err = pthread_create(&pid_detached, &attr, cb_detached, NULL); 
    if ( 0 != err ) 
    { 
        printf("can't create detached thread:%s\n", strerror(err)); 
    } 
    pthread_attr_destroy (&attr); 
 
    int **ret; 
    err = pthread_join(pid_joinable, (void**)ret); 
    if ( err == 0 ) 
    { 
        printf("joinable return %d\n", *ret); 
    } 
    else 
    { 
        printf("can't pthread_join pid_joinable thread: %s\n", strerror(err)); 
    } 
 
    err = pthread_join(pid_detached, (void**)ret); 
    if ( err == 0 ) 
    { 
        printf("pid_detached return %d\n", *ret); 
    } 
    else 
    { 
        printf("can't pthread_join pid_detached thread: %s\n", strerror(err)); 
    } 
 
    pthread_mutex_destroy(&mutex); 
 
    return 0; 
} 

编译运行:

g++ thread.cpp -o test -pthread
./test

输出结果如下所示:

New thread joinable begin pid 3330 tid 85509888 (0x518c700)
New thread joinable: pid 3330 tid 85509888 (0x518c700)
joinable runing 0
New thread detached begin pid 3330 tid 77117184 (0x498b700)
New thread detached: pid 3330 tid 77117184 (0x498b700)
detached runing 1
joinable runing 2
detached runing 3
detached runing 4
joinable runing 5
joinable runing 6
detached runing 7
detached runing 8
joinable runing 9
detached runing 10
joinable return 123
can't pthread_join pid_detached thread: Invalid argument

从结果可以看出,main函数阻塞到了这行代码:

err = pthread_join(pid_joinable, (void**)ret);

等线程工作完成后,通过此处对线程资源做了释放。
而pid_detached线程为detached属性,所以强行调用pthread_join函数会报错:

can't pthread_join pid_detached thread: Invalid argument

你可能感兴趣的:(C/C++,linux)