学习视频 <— 众所周知B站是中国最大的学习网站 2333
线程和进程的关系是:线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一用户内存空间,当进程退出时该进程所产生的线程都会被强制退出并清除。
一个进程至少需要一个线程作为它的指令执行体,进程管理着资源(比如cpu、内存、文件等等)。而将线程分配到某个cpu上执行。
因为线程和进程比起来很小,所以相对来说,线程花费更少的CPU资源。
在操作系统设计上,从进程演化出线程,最主要的目的就是更好地支持多处理器,并且减小进程上下文切换的开销。
首先在项目上右击,属性,依次点击
C/C++ Build -> Settings ->右边Tool Settings -> 下面GCC C Linker
在右上侧Command中添加 -lpthread
每个进程内部的不同线程都有自己的唯一标识(ID)
线程标识只在它所属的进程环境中有效
线程标识是 pthread_t 数据类型
#include
int pthread equal(pthread_t, pthread_t);
//返回:相等返回非0,否则返回O
pthread_t pthread_self(void);
//返回:调用线程的线程ID
tidp: 线程标识符指针
attr: 线程属性指针
start_rtn:线程运行函数的起始地址
arg:传递给线程运行函数的参数
新创建线程从 start_rtn 函数的地址开始运行
不能保证新线程和调用线程的执行顺序
#include
int pthread_create(pthread t *restrict tidp,
const pthread_attr_t *restrict attr,
void *(*start_rtn)(void*), void *restrict arg);
//返回:成功返回0,否则返回错误编号
//创建线程示例--->龟兔赛跑(初级版)
#include
#include
#include
#include
#include
//定义线程运行函数
void *th_fn(void *arg){
int distance=(int)arg;
int i;
for(i=1;i<=distance;i++){
printf("%lx run %d\n",pthread_self(),i);
int time=(int)(drand48()*10000);
usleep(time);//微秒
}
return (void*)0;
}
int main(void)
{
int err;//存储错误码
pthread_t rabbit,turtle;//定义兔子/乌龟线程
//创建rabbit线程
if((err=pthread_create(&rabbit,NULL,
th_fn,(void *)50))==-1){
perror("pthread_creat error");
}
//创建turtle线程
if((err=pthread_create(&turtle,NULL,
th_fn,(void *)50))==-1){
perror("pthread_creat error");
}
//主控线程调用pthread_join(),自己会阻塞
//直到rabbit和turtle线程结束方可运行
pthread_join(rabbit,NULL);
pthread_join(turtle,NULL);
//sleep(10);
printf("主控线程的ID:%lx\n",pthread_self());
printf("结束\n");
return 0;
}
//创建线程示例--->龟兔赛跑(升级版)
#include
#include
#include
#include
typedef struct{
char name[20];
int time;
int start;
int end;
}RaceArg;
void *th_fn(void *arg){
RaceArg *r=(RaceArg *)arg;
int i=r->start;
for(;i<=r->end;i++){
printf("%s (%lx) running %d\n",r->name,pthread_self(),i);
usleep(r->time);
}
return (void *)0;
}
int main(void){
int err;
pthread_t rabbit,turtle;
RaceArg r_a={"rabbit",(int)(drand48()*10000000),2,16};
RaceArg t_a={"turtle",(int)(drand48()*1000),1,15};
if((err=pthread_create(&rabbit,NULL,
th_fn,(void *)&r_a))==-1){
perror("pthread_create error");
}
if((err=pthread_create(&turtle,NULL,
th_fn,(void *)&t_a))==-1){
perror("pthread_create error");
}
pthread_join(rabbit,NULL);
pthread_join(turtle,NULL);
//sleep(5);
printf("主控线程ID:%lx\n",pthread_self());
printf("finish");
return 0;
}
#include
int pthread_cancel(pthread_ t tid);
void pthread_exit(void *retval);
int pthread_join(pthread_t th, void **thread_return);//特殊
返回值:成功返回0,否则返回错误编号
pthread_cancel
线程可以被同-进程的其他线程取消,tid为被终止的线程标识符。
pthread_exit
retval: pthread_exit调用者线程的返回值,可由其他函数和pthread_join来 检测获取。
线程退出时使用函数pthread_exit是线程的主动行为。
由于一个进程中的多个线程共享数据段,因此通常在线程退出后,
退出线程所占用的资源并不会随线程结束而释放。所有线程想结束后马上释放资源,就需要在主控线程中调用pthread_join函数来等待线程结束,类似于wait系统调用。
pthread_join
th:被等待线程的标识符
thread_return:用户定义指针,用来存储被等待线程的返回值
调用此方法的线程会被阻塞
//pthread_join等待线程结束并返回主线程值示例
#include
#include
#include
typedef struct{
int d1,d2;
}Arg;
void *th_fn(void *arg){
Arg *r=(Arg *)arg;
return (void *)(long)(r->d1+r->d2);
}
int main(void){
int err;
int *result;
int result2;
pthread_t th;
Arg r={20,50};
if((err=pthread_create(&th,NULL,th_fn,(void *)&r))==-1){
perror("pthread_create error");
}
//方法一
pthread_join(th,(void **)&result);
printf("result is %d\n",(int)result);
//方法二
//pthread_join(th,(void *)&result2);
//printf("result is %d\n",result2);
printf("主线程结束");
return 0;
}
#include
void pthread_cleanup_push(void (*rtn)(void *), void* arg);
void pthread_cleanup_pop(int execute);
返回:成功返回0,否则返回错误编号
这一组函数是成对出现和使用的
#include
#include
#include
//定义线程清理函数
void clean_fun(void *arg){
char *s=(char *)arg;
printf("clean_func: %s\n",s);
}
void *th_fn(void *arg){
int execute=(int)arg;
pthread_cleanup_push(clean_fun,"first clean func");
pthread_cleanup_push(clean_fun,"second clean func");
printf("thread running %lx\n",pthread_self());
pthread_cleanup_pop(execute);
pthread_cleanup_pop(execute);
return (void *)0;
}
int main(void){
int err;
pthread_t th1,th2;
if((err=pthread_create(&th1,NULL,th_fn,(void *)1))==-1){
perror("pthread_creat error");
}
pthread_join(th1,NULL);
printf("th1(%lx) finished\n",th1);
if((err=pthread_create(&th2,NULL,th_fn,(void *)1))==-1){
perror("pthread_creat error");
}
pthread_join(th2,NULL);
printf("th2(%lx) finished\n",th2);
return 0;
}
#include
int pthread_attr_getdetachstat(const pthread_attr_t *restrict attr,int *detachstate);
int pthread_attr_setdetachstat(const pthread_attr_t *attr,int detachstate);
返回:成功返回0,出错返回错误编号