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.
相关推荐
David猪大卫6 分钟前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯
Iceberg_wWzZ8 分钟前
数据结构(Day14)
linux·c语言·数据结构·算法
微尘810 分钟前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
五味香1 小时前
C++学习,动态内存
java·c语言·开发语言·jvm·c++·学习·算法
Aurora20051 小时前
蓝桥杯2024省C
c语言·算法·蓝桥杯
蟹至之1 小时前
字符函数 和 字符串函数 的使用与模拟
c语言·字符串·指针·const关键词
LaoWaiHang3 小时前
C语言从头学61——学习头文件signal.h
c语言
一名路过的小码农4 小时前
C/C++动态库函数导出 windows
c语言·开发语言·c++
m0_631270404 小时前
标准c语言(一)
c语言·开发语言·算法
万河归海4284 小时前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio