看这篇前强烈推荐先看一下第一部分
这篇我们主要介绍创建并操作线程的函数,有任何问题欢迎评论区留言,我们互相学习,共同进步!
创建线程函数 pthread_create
获取当前线程ID函数pthread_self
线程的创建
1 #include<stdio.h>
2 #include<pthread.h>
3 #include<unistd.h>
4
5 //线程要执行的函数
6 void* thread_run(void *args)
7 {
8 while(1)
9 {
10 printf("我是新线程[%s],我的线程ID是:%lun",(const char *)args, pthread_self());
11
12 sleep(1);
13 }
14 }
15
16 int main()
17 {
18 //创建新线程ID
19 pthread_t tid;
20 //创建新线程
21 pthread_create(&tid, NULL, thread_run, (void *)"thread 1");
22
23 while(1)
24 {
25 printf("我是主线程,我创建的线程ID是:%lun", tid);
26 sleep(1);
27 }
28
29 return 0;
30 }
使用前记得链接pthread库ubuntu linux,可参考上一节方法。
运行结果如下
左边可看到,我们主线程创建的新线程ID与新线程自己获得的ID是一样的,说明这个新线程确实是主线程创建出来的。
但这里有一个问题,根据上一节的介绍的LWP,我们发现我们创建出来线程的ID与LWP不同,但他们两个好像都表示了两个线程,
那么线程ID和内核中的LWP表示的是同一个线程吗? 是的!!!
请跳转到这里来看一下线程ID与内核LWP的关系
Linux线程ID与内核LWP的关系
下面是如何创建多个线程操作
1 #include<stdio.h>
2 #include<pthread.h>
3 #include<unistd.h>
4
5 //线程要执行的函数
6 void* thread_run(void *args)
7 {
8 while(1)
9 {
10 //printf("我是新线程[%s],我的线程ID是:%lun",(const char *)args, pthread_self());
11
12 sleep(3);
13 }
14 }
15
16 int main()
17 {
18 //创建新线程ID
19 pthread_t tid[5];
20 for(int i = 0 ; i < 5 ; i++)
21 {
22 pthread_create(tid + i, NULL, thread_run, (void *)"new thread");
23 }
24 //创建新线程
25
26 while(1)
27 {
28 printf("我是主线程, 我自己的线程ID是,%lun", pthread_self());
29 printf("################################begin###################################n");
30 for(int i = 0 ; i < 5 ; i++)
31 {
32 printf("我创建的线程[%d]ID是: %lun", i, tid[i]);
33 }
34 printf("#################################end####################################n");
35 sleep(1);
36 }
37
38 return 0;
39 }
运行结果如下:由下图可知,说明创建多个线程成功
线程等待函数pthread_join
注意线程等待的时候一定是阻塞式等待
通过线程等待函数我们就可以获取线程的返回值,从而通过返回值判断线程是否执行正确
获取线程返回值
运行结果说明成功接收到了新线程的返回值。
如果出现了代码异常pthread_join不需要处理,它只需要关心接收到的返回值是什么就行,处理异常的事情都交给主进程
这里我们只获得了一个线程的返回值,如果想获取多个,可以加个for循环pthread_join
线程的终止方案
1.函数中return(a. main函数退出return时候代表(主线程and进程退出)b.其他线程函数return,只代表当前线程退出)
2.新线程通过pthread_exit终止自己,如果用exit则会把整个进程都终止,所以如果只想终止一个线程用pthread_exit
3.取消目标线程,通过pthread_cancel函数,注意如果当前进程如果是被正常取消的话,join函数接收到的返回值是-1
线程分离
比如说我们主进程新创建了一个线程做一小部分任务,如果我们join获得这个新线程结束的返回值来判断任务是否完成的话,我们进程是处于阻塞等待的状态,效率降低,如果有些情况我们不需要获取到线程的返回值,让线程执行完任务就自己退出linux认证,这样就减少了阻塞等待的时间,提高效率。
根据上面的场景,我们接下来介绍下线程分离:
线程分离, 分离之后的线程不需要被join,运行完毕后linux判断线程是否在运行,会自动释放Z(僵尸)状态的PCBlinux判断线程是否在运行,这种机制和我们之间介绍过的信号处理的三种处理方法中的"忽略"很像。
对信号部分感兴趣的话也可以看一下
linux操作系统之进程信号(很详细)
线程分离函数pthread_detach
下面举例验证线程分离
由上面介绍join成功返回0!
运行结果如下,ret不是0,返回值也不是111,证明线程被分离了,join获取不到分离线程的退出码!
因此,一个线程被设置为分离之后,绝对不能再进行join了。
一般线程分离的场景为,主线程不退出,新线程处理完任务后自己退出。