Linux线程的属性

文章目录

  • 1.线程的属性
    • 1.1 查看线程属性
    • 1.2 属性变量的使用
  • 2. 分离属性
    • 2.1 僵尸线程
    • 2.2 分离与接合

1.线程的属性

1.1 查看线程属性

线程有许多属性,可以在终端中查看跟线程属性相关的函数:
敲入如下命令后连续按两下tab键

gec@ubuntu:~$ man pthread_attr_
pthread_attr_destroy          pthread_attr_getschedpolicy   pthread_attr_setaffinity_np   pthread_attr_setscope
pthread_attr_getaffinity_np   pthread_attr_getscope         pthread_attr_setdetachstate   pthread_attr_setstack
pthread_attr_getdetachstate   pthread_attr_getstack         pthread_attr_setguardsize     pthread_attr_setstackaddr
pthread_attr_getguardsize     pthread_attr_getstackaddr     pthread_attr_setinheritsched  pthread_attr_setstacksize
pthread_attr_getinheritsched  pthread_attr_getstacksize     pthread_attr_setschedparam    
pthread_attr_getschedparam    pthread_attr_init             pthread_attr_setschedpolicy   
gec@ubuntu:~$ 

可见,线程的属性多种多样,可以归总为如下表格:
获取属性API功能设置属性API功能pthread_attr_getdetachstate( )获取分离属性pthread_attr_setdetachstate( )设置分离属性pthread_attr_getguardsize( )获取栈警戒区大小pthread_attr_setguardsize( )设置栈警戒区大小pthread_attr_getinheritsched( )获取继承策略pthread_attr_setinheritsched( )设置继承策略pthread_attr_getschedpolicy( )获取调度策略pthread_attr_setschedpolicy( )设置调度策略pthread_attr_getschedparam( )获取调度参数pthread_attr_setschedparam( )设置调度参数pthread_attr_getscope( )获取竞争范围pthread_attr_setscope( )设置竞争范围pthread_attr_getaffinity_np( )获取CPU亲和度pthread_attr_setaffinity_np( )设置CPU亲和度pthread_attr_getstack( )获取栈指针和栈大小pthread_attr_setstack( )设置栈的位置和栈大小pthread_attr_getstacksize( )获取栈大小pthread_attr_setstacksize( )设置栈大小
这些属性可以在创建线程的时候,通过属性变量统一设置,有少部分可以在线程运行之后再进行设置(比如分离属性),下面介绍属性变量如何使用。

1.2 属性变量的使用

由于线程属性众多,因此需要的时候不直接设置,而是先将它们置入一个统一的属性变量中,然后再以此创建线程。属性变量是一种内置数据类型,需要用如下函数接口专门进行初始化和销毁:

#include 
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

线程属性的一般使用步骤:
定义且初始化属性变量 attr
将所需的属性,加入 attr 中
使用 attr 启动线程
销毁 attr
示例代码:

#include 
#include 
#include 
#include 
#include 

#include 
void *routine(void *arg __attribute__((unused)))
{
    sleep(1);
}
int main()
{
    // 初始化属性变量,并将分离属性添加进去
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    // 以分离属性启动线程
    pthread_t tid;
    pthread_create(&tid, &attr, routine, NULL);
    // 分离的线程无法接合
    if((errno=pthread_join(tid, NULL)) != 0)
        perror("接合线程失败");
    pthread_exit(NULL);
}

2. 分离属性

2.1 僵尸线程

默认情况下,线程启动后处于可接合状态(即未分离),此时的线程可以在退出时让其他线程接合以便释放资源,但若其他线程未及时调用 pthread_join() 去接合它,它将成为僵尸线程,浪费系统资源。
僵尸线程
因此,若线程退出时无需汇报其退出值,则一般要设置为分离状态,处于分离状态下的线程在退出之后,会自动释放其占用的系统资源。
将线程设置为分离状态有两种方式:
在线程启动前,使用分离属性启动线程
在线程启动后,使用 pthread_detach() 强制分离

2.2 分离与接合

在线程启动前,使用分离属性启动线程做法如下:

#include 
void *routine(void *arg)
{
    // ...
}
int main()
{
    // 初始化属性变量,并将分离属性添加进去
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    // 以分离属性启动线程
    pthread_t tid;
    pthread_create(&tid, &attr, routine, NULL);
    // ...
}

注意:
分离状态下的线程是无法被接合的。
在线程启动后,使用 pthread_detach() 强制分离的做法如下:

#include 
void *routine(void *arg)
{
    // 强制将自身设置为分离状态
    pthread_detach(pthread_self());
    // ...
}
int main()
{
    // 启动标准线程
    pthread_t tid;
    pthread_create(&tid, NULL, routine, NULL);
    // ...
}

编写一个程序,让主线程先退出并返回一个值,子线程接合主线程后输出主线程的退出值。

解答:

#include 
#include 
#include 

void *routine(void *arg)
{
    // 试图接合主线程,并获取其退出值
    void *val;
    pthread_t mid = *((pthread_t *)arg);
    pthread_join(mid, &val);

    printf("%s\n", (char *)val);
}

int main()
{
    pthread_t tid;
    pthread_t mid = pthread_self();
    pthread_create(&tid, NULL, routine, (void *)&mid);

    // 退出主线程
    pthread_exit("abcd");
}

你可能感兴趣的:(嵌入式Linux开发工程师课程,linux,多线程)