创建进程的函数
函数原型:
int pthread_create(
pthread_t *thread, //线程ID=无符号长整形
const pthread_attr_t *attr, //线程属性
void *(*start_routine)(void*), //函数指针线,程处理函数
void *arg //线程处理函数参数
);
参数;
thread:传出参数,线程创建成功之后,会被设置一个合适的值
attr:默认传NULL
start_routine:子线程的处理函数
arg:回调函数的参数
返回值
成功返回0
失败返回错误号
7 void * myfun()
8 {
9 //打印子线程的ID
10 printf("child pthid = %lu\n",pthread_self());
11 }
12
13 int main()
14 {
15 //‘定义一个线程的ID
16 pthread_t pthid;
17 pthread_create(&pthid,NULL,myfun,NULL);
18 //打印主进程的ID
19 printf("parent pthid = %lu\n",pthread_self());
20 int i = 0;
21 for(i;i < 4;i++)
22 {
23 printf("i = %d\n",i);
24 }
25 sleep(2); //这里主线程需要等子进程执行完之后在结束,如果不等子线程执行的话,主进程执行完就会释放内存空间,这时候子线程还没有执行就会随着父线程的结束而结束
26 return 0;
27 }
主函数中的代码是主线程执行的部分,回调函数中是子线程执行的部分
线程创建的过程
所以说在linux中,内核把线程和进程一样来管理,线程是轻量级进程,内核只认识pcb
主线程和子线程共享哪些东西?不共享哪些?
共享的:.text段,.bss段 .data段, 堆,动态库加载区
不共享:栈不共享
注意:如果创建5个线程的话,这5个线程平均分配这个栈
线程间通信是通过什么来通信的?
堆和全局变量
相关函数
1.定义线程ID
函数原型:pthread_t pthid;
2.获取线程的ID
函数原型:pthread_self()
3.单个线程退出函数
函数原型:pthread_exit(void* retval); retval相当于返回值
retval指针:必须是全局变量或者堆
4.阻塞等待线程退出,获取线程退出状态,和进程中的wait()和waitpid()作用一样
函数原型:int pthread_join(pthread_t thread,void ** retval)
参数:
thread :要回收的子线程的线程id
retval:读取线程退出的时候携带的状态信息
void *ptr
pthread_jion(pthid,&ptr); //指向的内存和pthread_exit()中携带的参数是一样的
8 void* fun()
9 {
10 printf("child pthid = %lu\n",pthread_self());
11
12 //单个线程退出,如果没有单个线程推出函数,那就只有跟随主线程的退出才能退
出
13 pthread_exit(NULL);
14 }
15
16 int main()
17 {
18 //定义一个线程ID
19 pthread_t pthid;
20 //创建线程
21 pthread_create(&pthid,NULL,fun,NULL);
22 //打印线程的线程ID
23 printf("parent pthid = %lu\n",pthread_self()); //%lu是打印无符号的长整型
24
25 int i = 0;
26 for(;i < 3;i++)
27 {
28 printf("nihao!\n");
29 }
30
31 //阻塞等待线程退出,获取子线程的退出状态
32 pthread_join(pthid,NULL);
33 return 0;
34 }
5.线程分离 pthread_detach
函数原型:int pthread_detach(pthread_t thread);
调用该函数之后不需要pthread_join
子线程会自动回收自己的pcb
6.杀死线程
函数原型:int pthread_cancel(pthread_t thread);
注意事项:
在要杀死的子线程对应的处理的函数的内部,必须做有系统调用
如果子线程中没有系统调用,则设置一个专门的调用函数pthread_testcancel()就可以杀死它
7.比较两个线程的ID是否相等
pthread_t 无符号长整形,所以可以直接比较
函数原型:int pthread_equal(pthread_t t1,pthread_t t2);
给未来预留的
线程分离基本流程
对线程要分离的话需要在创建线程的第二个属性上操作就可以
线程属性的类型:pthread_attr_t attr;
线程属性变量的初始化
int pthread_attr_init(pthread_attr_t* attr);
设置线程分离属性
int pthread_attr_setdetachstate(
pthread_attr_t* attr,
int detachstate;
);
参数
attr:线程属性
detachstate
PTHREAD_CREATE_DETACHED(分离)
PTHREAD_CREATE_JOINABLE(非分离)
释放线程资源函数
int pthread_attr_destroy(pthread_attr_t* attr);
7 void * myfun()
8 {
9
10 //打印子线程的ID
11 printf("child pthid = %lu\n",pthread_self());
12
13 }
14
15 int main()
16 {
17 //‘定义一个线程的ID
18 pthread_t pthid[5];
19 int i = 0;
20 //创建5个线程,并且创建的时候设置线程分离
21 //初始化线程分离
22 pthread_attr_t attr;
23 pthread_attr_init(&attr);
24 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
25
26 for(;i<5;i++)
27 {
28 pthread_create(&pthid[i],&attr,myfun,NULL);
29 }
30
31 //打印主进程的ID
32 printf("parent pthid = %lu\n",pthread_self());
33
34 //释放线程资源
35 pthread_attr_destroy(&attr);
36 return 0;
37 }