概念:
进程内的一个执行单元,执行的一段程序片段。共享全局变量。(和主函数同时执行的子函数就是一个线程)(hello world程序,可以说是一个进程,也可以说是一个线程)。
参考手册:
man 7 threads
查看线程:
命令:
ps -T -p <pid>————查看该pid的线程
top -H -p <pid>————开启线程查看
htop——设置:F2(开启“树状视图”查看)(开启“显示自定义线程”选项)F10(退出设置)
文件:
/proc/PID/task/————线程默认的名字和进程名相同
/proc/PID/task/comm——线程名
PS:PID为要查的PID号,没有PID这个文件夹。
获取线程标识:
pthread_t pthread_self(void);
返回值——当前线程的线程ID,用%lu打印。
获取/设置线程名字:
int prctl(int option,unsigned long arg2);
option:
PR_GET_NAME——获取当前线程的名字
PR_SET_NAME——设置当前线程名字(宏定义为9)
arg2:
线程名的长度最大为15字节,且应该以‘\0’结尾(共计最多16个字符)
返回值:
0——成功
-1——出错
代码:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h>
int main(){
printf("PID:%d,TID:%lu\n",getpid(),pthread_self());
char name[16] = {0};
prctl(PR_SET_NAME,"test");
prctl(PR_GET_NAME,name);
printf("TNAME:%s\n",name);
}
创建进程:
int pthread_create(pthread_t* tidp,pthread_attr* attr,void* (*start_rtn)(void),void* arg);
tidp:
线程ID指针。
start_rtn:
函数指针。
arg:
start_rtn指向函数的形参。
返回值:
0——成功
非0——出错
attr:
写NULL即可。
代码:
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h>
int info(){
printf("PID:%d,TID:%lu",getpid(),pthread_self());
char name[16] = {0};
prctl(PR_GET_NAME,name);
printf("TNAME:%s\n",name);
}
void* method(void* arg){
info();
}
int main(){
info();
printf("PID:%d,TID:%lu\n",getpid(),pthread_self());
pthread_t tid;
pthread_create(&tid,NULL,method,NULL);
printf("new tid:%lu\n",tid);
sleep(1);
}
正常终止线程:
子线程:
1.return:
线程处理函数。
2.void pthread_exit(void* retval);
函数的返回指针,用pthread_join函数的第二个参数进行接收。(用在线程回调函数中,返回线程数据)
主线程:
1.线程合并:
可由其他线程终止,回收资源。
int pthread_join(pthread_t tid,void** retval);
tid——被等待的线程标识符。
retval——一个用户定义的指针,可以用来存储被等待进程的返回值。
返回值——0为成功,非0为错误码。
代码:
#include <pthread.h>
#include <sys/prctl.h>
int info(){
printf("PID:%d,TID:%lu",getpid(),pthread_self());
char name[16] = {0};
prctl(PR_GET_NAME,name);
printf("TNAME:%s\n",name);
}
void* method(void* arg){
sleep(5);
info();
}
int main(){
info();
pthread_t tid;
pthread_create(&tid,NULL,method,NULL);
printf("new tid:%lu\n",tid);
//sleep(1);
pthread_join(tid,NULL);
}
2.线程分离:
不能被其他线程终止,存储资源在它终止时由系统自动回收释放。
int pthread_detach(pthread_t tid);
tid——要释放线程的标识符ID
返回值——0为成功,非0为错误码。
代码:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <string.h>
#include <errno.h>
int info(){
printf("PID:%d,TID:%lu",getpid(),pthread_self());
char name[16] = {0};
prctl(PR_GET_NAME,name);
printf("TNAME:%s\n",name);
}
void* method(void* arg){
sleep(15);
info();
printf("arg:%s",arg);
}
pthread_t create_thread(){
pthread_t tid;
static char test[] = "Hello thread";
pthread_create(&tid,NULL,method,(void*)test);
pthread_detach(tid);
return tid;
}
int main(){
info();
pthread_t tid;
//char test[]="hello thread";
//pthread_create(&tid,NULL,method,test);
tid = create_thread();
printf("new tid:%lu\n",tid);
//sleep(1);
int err;
if((err = pthread_join(tid,NULL))!=0){
fprintf(stderr,"pthread_join error:%s",strerror(err));
return 1;
}
}
并发度:
设置并发数——int pthread_setconcurrency(int level);
获取并发数——int pthread_getconcurrency(void);
代码:
#include <pthread.h>
#include <sys/prctl.h>
long ticket = 1000000;
void* method(void* arg){
while(ticket > 0){
ticket--;
printf("%lu get a ticket, leave %d\n",pthread_self(),ticket);
//sleep(1);
}
}
int main(){
pthread_t tid;
pthread_setconcurrency(5);
pthread_create(&tid,NULL,method,NULL);
pthread_create(&tid,NULL,method,NULL);
pthread_create(&tid,NULL,method,NULL);
pthread_create(&tid,NULL,method,NULL);
pthread_create(&tid,NULL,method,NULL);
pause();
}
自动释放资源:
void pthread_cleanup_push(void(*routine)(void*),void* arg);
void pthread_cleanup_pop(execute);
PS:execute通常为0;两个函数要配套使用(宏定义时分别包含左右大括号);routine为free。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/prctl.h>
int info(){
printf("PID:%d,TID:%lu",getpid(),pthread_self());
char name[16] = {0};
prctl(PR_GET_NAME,name);
printf("TNAME:%s\n",name);
}
void* method(void* arg){
pthread_cleanup_push(free,arg);
sleep(5);
info();
printf("arg:%s",arg);
//free(arg);
pthread_cleanup_pop(0);
}
pthread_t create_thread(){
pthread_t tid;
char* test = malloc(BUFSIZ);
strcpy(test,"Hello thread");
pthread_create(&tid,NULL,method,(void*)test);
return tid;
}
int main(){
info();
pthread_t tid;
//char test[]="hello thread";
//pthread_create(&tid,NULL,method,test);
tid = create_thread();
printf("new tid:%lu\n",tid);
//sleep(1);
pthread_join(tid,NULL);
}
线程取消:
取消点:如果线程接收到取消信号,系统默认,到达指定位置才能取消。
设置取消点——void pthread_testcancel(void);
PS:许多函数默认自带取消点(printf()/sleep()),在man 7 pthreads中查看详情。
发送取消信号:
int pthread_cancel(pthread_t thread);
thread——要结束的线程ID。
返回值——0为成功,否则失败。
设置当前线程的取消状态:
int pthread_setcancelstate(int state,int* oldstate);
state:
PTHREAD_CANCEL_ENABLE——允许取消(默认)
PTHREAD_CANCEL_DISABLE——禁用取消(谁都无法取消该线程,传信号没用,即使是强制取消也没用)
oldstate——之前的取消状态。
设置当前线程的取消类型:
int pthread_setcanceltype(int type,int* oldtype);
type:
PTHREAD_CANCEL_DEFFERED——————取消点退出(默认)
PTHREAD_CANCEL_ASYNCHRONOUS———立即退出(强制取消)
代码:
#include <stdio.h>
#include <pthread.h>
long count = 0;
void* default_func(void* arg){
for(;;){
pthread_testcancel();
count++;
}
}
void* disable_func(void* arg){
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
for(;;){
pthread_testcancel();
count++;
}
}
void* force_func(void* arg){
pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
for(;;){
count++;
}
}
void* disable_force_func(void* arg){
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
for(;;){
count++;
}
}
void* watch(void* arg){
for(;;){
sleep(1);
printf("count:%d\n",count);
}
}
void* cancel(void* arg){
sleep(5);
pthread_t* ptid = arg;
printf("cancel %lu\n",ptid[0]);
pthread_cancel(ptid[0]);
}
int main(int argc,char* argv[]){
typedef void* (*Func)(void*);
Func funcs[3] = {default_func,watch,cancel};
int c;
while((c=getopt(argc,argv,"dp"))!=-1){
switch(c){
case 'd':
funcs[0] = (funcs[0] == default_func?disable_func:disable_force_func);
break;
case 'p':
funcs[0] = (funcs[0] == default_func?force_func:disable_force_func);
break;
}
}
pthread_t tids[3];
int i=0;
for(;i<3;i++){
pthread_create(&tids[i],NULL,funcs[i],&tids);
printf("create thread %lu\n",tids[i]);
}
for(i=0;i<3;i++){
pthread_join(tids[i],NULL);
}
}
发送信号:
发送的信号对所有线程都起作用!
int pthreead_kill(pthread_t tid,int sig);
tid——线程ID
sig——信号:
0———保留信号,用来测试线程是否存在。
正数——系统调用信号或自定义信号。
返回值:
0————调用成功
ESRCH——线程不存在
EINVAL——信号不合法
代码:
if(0 != pthread_kill(ptid[0].tid,0)){
printf("%lu dead\n",ptid[0].tid);
break;
}else{
printf("%lu live\n",ptid[0].tid);
}