5.3 连接和分离线程

方法

pthread_join(thread, status)

pthread_detach(thread)

pthread_attr_setdetachstate(attr, detachstate)

pthread_attr_getdetachstate(attr)

连接

连接(joining)是一种线程之间完成同步的方法,举例如下。

pthread_join()方法会阻塞调用它的线程,直到相关的线程终止运行。如果相关线程调用了pthread_exit(),编程人员能够在主线程中获取相关线程终止时的具体信息(即pthread_exit()的参数会传递给pthread_join())。

一个线程只能被连接一次,对单个线程进行多次连接错误会导致逻辑错误。

用于线程间同步的另外两种方法:互斥量和条件变量将在后续章节中讲述。

能否连接

线程被创建时,它的一个属性决定其是能够被连接的或者是已经分离的,只有属性为能够被连接的线程才可以通过调用pthread_join() 对其进行连接。如果一个线程的属性为已分离的,那么它不能够被连接。

POSIX标准中要求创建的线程应该为可连接的。我们可以通过设置pthread_create()中的attr参数来设置创建线程时的这个属性,对attr的使用流程如下。

  • 声明一个pthread_attr_t类型的变量
  • 使用pthread_attr_init()对其初始化
  • 使用pthread_attr_setdetachstate()设置变量的可连接/分离属性
  • 变量使用结束后,使用pthread_attr_destroy()销毁该变量

分离

pthread_detach()方法用于显式地分离一个线程,即使它被创建时相关属性为可连接;没有对应的逆向操作的方法。

建议

如果一个线程需要被连接,在创建它时就设为可连接的属性。因为一些平台的实现中线程创建时可能属性的默认值不是可连接的,这样做代码的健壮性、可移植性更高。

如果事先确定一个线程永远不可能被连接,可以考虑将其初始化时的属性设为分离的,这样可以减少系统负载。

示例程序

/*****************************************************************************
* FILE: join.c
* DESCRIPTION:
*   This example demonstrates how to "wait" for thread completions by using
*   the Pthread join routine.  Threads are explicitly created in a joinable
*   state for portability reasons. Use of the pthread_exit status argument is 
*   also shown. Compare to detached.c
* AUTHOR: 8/98 Blaise Barney
* LAST REVISED:  01/30/09
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS	4

void *BusyWork(void *t)
{
    int i;
    long tid;
    double result=0.0;
    tid = (long)t;
    printf("Thread %ld starting...\n",tid);
    for (i=0; i<1000000; i++)
        {
            result = result + sin(i) * tan(i);
        }
    printf("Thread %ld done. Result = %e\n",tid, result);
    pthread_exit((void*) t);
}

int main (int argc, char *argv[])
{
    pthread_t thread[NUM_THREADS];
    pthread_attr_t attr;
    int rc;
    long t;
    void *status;

    /* Initialize and set thread detached attribute */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for(t=0; t<NUM_THREADS; t++) {
        printf("Main: creating thread %ld\n", t);
        rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }

    /* Free attribute and wait for the other threads */
    pthread_attr_destroy(&attr);
    for(t=0; t<NUM_THREADS; t++) {
        rc = pthread_join(thread[t], &status);
        if (rc) {
            printf("ERROR; return code from pthread_join() is %d\n", rc);
            exit(-1);
        }
        printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
    }

    printf("Main: program completed. Exiting.\n");
    pthread_exit(NULL);
}

运行后输出信息如下

Main: creating thread 0
Main: creating thread 1
Thread 0 starting...
Main: creating thread 2
Thread 1 starting...
Main: creating thread 3
Thread 2 starting...
Thread 3 starting...
Thread 1 done. Result = -3.153838e+06
Thread 0 done. Result = -3.153838e+06
Main: completed join with thread 0 having a status of 0
Main: completed join with thread 1 having a status of 1
Thread 3 done. Result = -3.153838e+06
Thread 2 done. Result = -3.153838e+06
Main: completed join with thread 2 having a status of 2
Main: completed join with thread 3 having a status of 3
Main: program completed. Exiting.
相关推荐
闲晨4 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
DARLING Zero two♡9 小时前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
QAQ小菜鸟10 小时前
一、初识C语言(1)
c语言
何曾参静谧10 小时前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
互联网打工人no110 小时前
每日一题——第一百二十一题
c语言
朱一头zcy11 小时前
C语言复习第9章 字符串/字符/内存函数
c语言
此生只爱蛋12 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
何曾参静谧12 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
lulu_gh_yu13 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
~yY…s<#>14 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode