线程概念:(1)轻量级的进程,一个进程内部可以有多个线程,默认情况下一个进程只有一个线程。(2)线程是最小的执行单元,进程是最小的系统资源分配单位。(3)内核实现都是通过clone函数实现,线程也有自己的PCB。
查看pthread库版本命令:
~$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.23
1.创建线程示例:cat pthread_create.c
#include<unistd.h>
#include<pthread.h>
#include <stdio.h>
void *thr(void *arg)
{
printf("I am a thread!pid=%d,tid=%lu\n",getpid(),pthread_self());
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,thr,NULL);
printf("I am a MAIN thread!pid=%d,tid=%lu\n",getpid(),pthread_self());
pthread_exit(NULL);
return 0;
}
pthread_self() :函数获得自身线程ID
编译:gcc file.name -lpthread
- 在编译的时候也可以写脚本自动生成makefile文件–>make 编译
- 在/home目录下.bashrc增加:alias echomake=‘cat ~/bin/makefile.template (根据自己文件名字)>> makefile’
- $cat ~/bin//makefile.template
#create by ** 2021.2.21
SrcFiles=$(wildcard *.c)
TargetFiles=$(patsubst %.c,%,$(SrcFiles))
all:$(TargetFiles)
%:%.c
gcc -o $@ $< -lpthread -g
clean:
-rm -f $(TargetFiles)
- $echomake -->生成makefile文件 (未实现??)
2.线程退出
pthread_exit(): 线程退出函数。线程退出注意事项:
- 在线程中使用pthread_exit()
- 在线程中使用return(主控线程return代表退出进程)
- exit代表退出整个进程
3.线程回收
int pthread_join(pthread_t thread, void **retval);
线程回收函数–阻塞等待回收
- thread 线程创建的时候传出的第一个参数
- retval 代表传出线程的退出信息
实例:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void *thr(void *arg)
{
printf("I am a thread,tid=%lu\n",pthread_self());
sleep(5);
printf("I am a thread,tid=%lu\n",pthread_self());
pthread_exit((void*)101);
//return (void*)100;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,thr,NULL);
void *ret;
pthread_join(tid,&ret); //线程回收
printf("ret exit with %d\n",(int)ret);
pthread_exit(NULL);
}
输出:
~$ gcc pthread_rtn.c -lpthread
~$ ./a.out
I am a thread,tid=140591370012416
I am a thread,tid=140591370012416
ret exit with 101
4.杀死线程
pthread_cancel()函数
原型:int pthread_cancel(pthread_t thread);
- 需要输入tid;
- 返回值:
失败返回errno,成功返回0
pthread_cancel杀死的线程,退出状态为PTHREAD_CANCELED
#define PTHREAD_CANCELED ((void*)-1)
示例:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void *thr(void *arg)
{
while (1)
{
printf("I am a thread,keep running still be canceled!tid=%lu\n",pthread_self());
sleep(1);
}
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,thr,NULL);
sleep(5);
pthread_cancel(tid); //杀死线程
void *ret;
pthread_join(tid,&ret); //线程回收
printf("ret exit with %d\n",(int)ret); //打印被杀死后的退出状态
pthread_exit(NULL);
}
输出:
~$ gcc pthread_cancel.c -lpthread
~$ ./a.out
I am a thread,keep running still be canceled!tid=140291370272512
I am a thread,keep running still be canceled!tid=140291370272512
I am a thread,keep running still be canceled!tid=140291370272512
I am a thread,keep running still be canceled!tid=140291370272512
I am a thread,keep running still be canceled!tid=140291370272512
ret exit with -1
5.线程分离
注意最后一句:如果一个线程调用pthread_detach()线程分离(自动回收机制),就不能再调用pthread_join()函数进行线程回收了。
示例:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
void *thr(void *arg)
{
printf("I am a thread,keep running still be canceled!tid=%lu\n",pthread_self());
sleep(4);
printf("I am a thread,keep running still be canceled!tid=%lu\n",pthread_self());
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,thr,NULL);
pthread_detach(tid); //线程分离
int ret = 0;
//void *tt;
if((ret = pthread_join(tid,NULL)) > 0) //判定分离之后是否还能回收
{
//printf("ret exit with %d\n",(int)tt); //打印被杀死后退出状态,线程分离时应不存在
printf("join err:%d,%s\n",ret,strerror(ret));
}
return 0;
}
输出:
~$ gcc pthread_detach.c -lpthread
~$ ./a.out
join err:22,Invalid argument
pthread_equal()函数:比较两个线程是否相等。
int pthread_equal(pthread_t t1, pthread_t t2);
有可能Linux未来线程ID pthread_t类型被修改为结构体实现。
6.创建多线程
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void *thr(void *arg)
{
int num = (int)arg;
printf("I am %d thread,self=%lu\n",num,pthread_self());
return (void *)(100+num);
//pthread_exit(NULL);
}
int main()
{
pthread_t tid[5];
int i;
for(i=0; i<5; i++)
{
pthread_create(&tid[i],NULL,thr,(void *)i);
sleep(1);
}
for(i=0; i<5; i++)
{
void *ret;
pthread_join(tid[i],&ret); //有序回收线程
printf("i == %d, ret == %d\n",i,(int)ret);
}
return 0;
}
输出:
~$ gcc npthreads.c -lpthread
~$ ./a.out
I am 0 thread,self=139840462472960
I am 1 thread,self=139840454080256
I am 2 thread,self=139840377059072
I am 3 thread,self=139840368666368
I am 4 thread,self=139840360273664
i == 0, ret == 100
i == 1, ret == 101
i == 2, ret == 102
i == 3, ret == 103
i == 4, ret == 104
7.线程属性
- 线程控制
int pthread_attr_init(pthreat_attr_t *attr); //初始化线程
int pthread_attr_destroy(pthreat_attr_t *attr); //销毁线程 - 设置线程分离状态/非分离状态方法:
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); //设置属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); //获得属性
参数:attr 线程已初始化属性
detachstate:设置属性,PTHREAD_CREATE_DETACHED 分离线程
PTHREAD_CREATE_DETACHED 非分离线程
示例:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
void *thr(void *arg)
{
printf("I am a thread\n");
}
int main()
{
pthread_attr_t attr;
pthread_attr_init(&attr); //初始化属性
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); //设置属性分离状态
pthread_t tid;
pthread_create(&tid,&attr,thr,NULL);
//线程回收
int ret;
if((ret = pthread_join(tid,NULL)) > 0)
{
printf("join err:%d,%s\n",ret,strerror(ret));
}
pthread_attr_destroy(&attr); //摧毁属性
return 0;
}