多线程编程
来源:互联网 发布:人工智能技术专业 编辑:程序博客网 时间:2024/06/07 02:34
概念:
进程内的一个执行单元,执行的一段程序片段。共享全局变量。(和主函数同时执行的子函数就是一个线程)(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);}
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- theano调试技巧
- mybatis如何根据mapper接口生成其实现类
- 打造炫酷通用的ViewPager指示器
- Spring Cloud学习 | 第一章 | 背景介绍
- SQL Server 的“高可用性”与“灾难恢复” 之二 故障转移群集
- 多线程编程
- FILE *stdout 和 STDOUT_FILENO 的区别
- 破解前端面试系列(3):如何搞定纸上代码环节?
- 金蝶EAS,序时簿界面去除数据隔离,根据枚举项实现背景色标记,数据排序
- [Androrid]笔记9-用户友好的输入界面
- tcp/ip和udp之间的区别
- 第九周作业:Fizz Buzz
- Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds.
- MySQL(二):MySQL性能优化