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.
相关推荐
珹洺2 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
.Cnn3 小时前
用邻接矩阵实现图的深度优先遍历
c语言·数据结构·算法·深度优先·图论
2401_858286113 小时前
101.【C语言】数据结构之二叉树的堆实现(顺序结构) 下
c语言·开发语言·数据结构·算法·
寻找码源4 小时前
【头歌实训:利用kmp算法求子串在主串中不重叠出现的次数】
c语言·数据结构·算法·字符串·kmp
带多刺的玫瑰5 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
陌小呆^O^6 小时前
Cmakelist.txt之win-c-udp-server
c语言·开发语言·udp
时光の尘6 小时前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
-一杯为品-6 小时前
【51单片机】程序实验5&6.独立按键-矩阵按键
c语言·笔记·学习·51单片机·硬件工程
爱摸鱼的孔乙己7 小时前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
Dola_Pan7 小时前
C语言:数组转换指针的时机
c语言·开发语言·算法