LV05-02-线程-04-线程分离

本文主要是进程——线程分离的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日
开发板 正点原子 i.MX6ULL Linux阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
STM32开发板 正点原子战舰V3(STM32F103ZET6)
点击查看本文参考资料
参考方向 参考原文
------
点击查看相关文件下载
--- ---

一、什么是线程分离

默认情况下,当线程终止时,其它线程可以通过调用 pthread_join() 获取其返回状态、回收线程资源。可是有时候,我们并不关心线程的返回状态,只是希望系统在线程终止时能够自动回收线程资源并将其移除。在这种情况下,可以调用 pthread_detach() 将指定线程进行分离,也就是分离线程。分离线程后,线程结束也不会产生僵尸线程。

二、分离函数

1. pthread_detach()

1.1 函数说明

在 linux 下可以使用 man pthread_detach 命令查看该函数的帮助手册。

1
2
3
/* Compile and link with -pthread. */
#include <pthread.h>
int pthread_detach(pthread_t thread);

【函数说明】该函数将指定线程进行分离。

【函数参数】

  • thread : pthread_t 类型,参数 thread 指定需要分离的线程的线程 ID 。

【返回值】 int 类型,成功返回 0 ,失败将返回错误码。

【使用格式】一般情况下基本使用格式如下:

1
2
3
4
5
6
7
/* 需要包含的头文件 */
#include <pthread.h>

/* 至少应该有的语句 */
pthread_cancel(tid);
/* 或者在自己的线程中分离自己 */
pthread_detach(pthread_self());

【注意】

(1)一个线程既可以将另一个线程分离,同时也可以将自己分离。

(2)设置了线程分离之后,就无法通过 pthread_join() 来获取已结束线程的信息了, pthread_join() 函数将会返回错误信息。

1.2 使用实例

点击查看实例
test.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <pthread.h>/* pthread_create pthread_exit pthread_self pthread_join pthread_detach*/
#include <unistd.h> /* sleep */
#include <string.h> /* strerror */

void *threadDetach(void *arg);


int main(int argc, char *argv[])
{
int ret;
pthread_t tid;
/* 1. 创建一个线程 */
ret = pthread_create(&tid, NULL, threadDetach, NULL);
printf("This is main thread,ret=%d,tid=%lu\n", ret, tid);

/* 2. 主线程分离子线程或者在子线程中分离自己 */
// pthread_detach(tid);
sleep(5);
/* 3. 分离后进行回收,若分离成功,则会出错 */
ret = pthread_join(tid, NULL);
if(ret != 0)
printf("pthread_join error: %s\n", strerror(ret));

return 0;
}

void *threadDetach(void *arg)
{
/* 自行分离 */
pthread_detach(pthread_self());

printf("This is a thread test! pid=%d,tid=%lu\n", getpid(), pthread_self());
sleep(3);
pthread_exit("thread return!");
}

在终端执行以下命令编译程序:

1
2
gcc test.c -Wall -l pthread # 生成可执行文件 a.out 
./a.out # 执行可执行程序

然后,终端会有以下信息显示:

1
2
3
This is main thread,ret=0,tid=139858080994880
This is a thread test! pid=4353,tid=139858080994880
pthread_join error: Invalid argument

三、分离状态属性

除了使用 pthread_detach 函数来设置线程分离,还可以通过设置创建线程时的属性来达到线程分离的效果,详情可以查看上一节的笔记。

四、内存演示

与前边的线程回收一节中的内存演示步骤及判断方式一样。不过此处我有一点点的疑问,就是我使用 Ubuntu21.04 的 64 位时候,内存似乎还变大了,但是我使用 Ubuntu14.04 的 32 位版本就是正常的,这个原因嘛,我还没找到,先这样记着,后边搞明白了再补充。

点击查看测试程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <pthread.h>/* pthread_create pthread_exit pthread_self pthread_join pthread_detach*/
#include <unistd.h> /* sleep */

#define pthreadDetach

void *threadDetach(void *arg);

int main(int argc, char *argv[])
{
int ret;
int i = 0;
pthread_t tid[100];
/* 1. 创建线程 */
for(i=0; i<100; i++)
{
ret = pthread_create(&tid[i], NULL, threadDetach, (void *)i);
printf("This is [%d] thread,ret=%d,tid=%lu\n",i, ret, tid[i]);
}

while(1)
{
sleep(1);
}
return 0;
}

void *threadDetach(void *arg)
{
#ifdef pthreadDetach
/* 自行分离 */
pthread_detach(pthread_self());
#endif
printf("This is [%d] thread test! pid=%d,tid=%lu\n", (int)arg, getpid(), pthread_self());
sleep(25);
pthread_exit("thread return!");
}