Skip to content

线程属性

linux下线程的属性是可以根据实际项目需要进行设置,之前讨论的线程都是采用线程的默认属性,默认属性已经可以解决绝大多数开发时遇到的问题,如果对程序的性能提出更高的要求,则需要设置线程属性,本节以设置线程的分离属性为例讲解设置线程属性。

线程的分离状态决定一个线程以什么样的方式来终止自己,有两种状态:

  • 非分离状态:线程的默认属性是非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。
  • 分离状态:分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。应该根据自己的需要,选择适当的分离状态。

设置线程属性分为以下步骤

第1步:定义线程属性类型类型的变量

cpp
pthread_attr_t  attr;

第2步:对线程属性变量进行初始化

cpp
int pthread_attr_init (pthread_attr_t* attr);

第3步:设置线程为分离属性

cpp
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

参数:

  • attr:线程属性
  • detachstate:线程detach的状态
    • PTHREAD_CREATE_DETACHED(分离)
    • PTHREAD_CREATE_JOINABLE(非分离)
  • 注意:这一步完成之后调用pthread_create函数创建线程,则创建出来的线程就是分离线程;其实上述三步就是pthread_create的第二个参数做准备工作。

第4步:释放线程属性资源

cpp
int pthread_attr_destroy(pthread_attr_t *attr);

参数:线程属性

练习:编写程序,创建一个分离属性的线程。

cpp
/**
 * 线程属性
 * The  attr  argument  points  to  a  pthread_attr_t  structure  whose  contents  are used at thread creation time to determine attributes for the new thread; this structure is initialized using pthread_attr_init(3) and related functions.  If attr is NULL, then the thread is created with default attributes.
 * attr参数指向一个pthread_attr_t结构体,该结构体的内容在线程创建时用于确定新线程的属性;这个结构是用pthread_attr_init(3)和相关函数初始化的。如果attr为NULL,则使用默认属性创建线程。
*/

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void threadMain(void *arg) {
    printf("Hello, I'm a child thread and I'm starting to execute.\n");
    sleep(3);
    printf("Hello, I'm a child thread. I'm done.\n");
    pthread_exit((void *) 20);
}

int main(int argc, char const *argv[]) {
    // 线程tid
    pthread_t tid;
    // 线程属性结构体
    pthread_attr_t attr; 
    // 初始化线程属性结构体
    pthread_attr_init(&attr); 
    // 将线程属性设置为detach分离状态
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    // 使用设置好的线程属性创建线程
    pthread_create(&tid, &attr, (void *) threadMain, NULL); 

    void *ptr;
    int ret = pthread_join(tid, &ptr);
    if (ret != 0) {
        printf("Join faild, ret num is %d. Thread is detach.\n");
    } else {
        printf("Join finish, ret num is %d. Thread is not detach.\n");
    }

    pthread_exit((void *) 0);
}

程序输出:

shell
$ gcc thread_attr.c -o a -pthread 
thread_attr.c: In function ‘main’:
thread_attr.c:28:41: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat=]
   28 |         printf("Join faild, ret num is %d. Thread is detach.\n");
      |                                        ~^
      |                                         |
      |                                         int
thread_attr.c:30:42: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat=]
   30 |         printf("Join finish, ret num is %d. Thread is not detach.\n");
      |                                         ~^
      |                                          |
      |                                          int
$ ./a
Join faild, ret num is 948855112. Thread is detach.
Hello, I'm a child thread and I'm starting to execute.
Hello, I'm a child thread. I'm done.

验证:设置为分离属性的线程是不能够被pthread_join函数回收的,可以通过调用pthread_join函数测试该线程是否已经是分离属性的线程。