一、线程的基础
二、线程的创建、退出、分离、汇合
三、线程对共享资源的访问
四、线程的同步
以下线程皆为posix线程
一、线程的基础
进程是资源分配的基本单位,线程是执行的基本单位。
一个进程中可以有多个线程,但至少要有一个主线程。
线程共享进程资源。线程切换和线程通讯都很灵活。每个线程都有自己独有的属性。线程的ID(tid)、线程的自己栈帧、自己的信号屏蔽字(但是共享进程的信号的处理函数)
二、线程的创建、退出、分离、汇合
1、创建线程使用pthread_create(3),编译时需要使用pthread动态链接库(-lpthread)
头文件
#include<pthread.h>
函数声明
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void*(*start_routine)(void*), void * arg);
功能:
在当前进程创建一个新线程,新线程执行start_routine函数的代码,arg作为其唯一的参数被传递
参数:
thread:新线程的ID
attr:线程属性参数,需要使用pthread_attr_init(3)进行初始化,如果为NULL,则使用默认属性
start_routine:线程的执行函数
arg:线程执行函数的唯一的参数
返回值:
成功:0
错误:返回一个错误码,且*thread的内容不被定义
例:
#include<stdio.h> #include<pthread.h> void *doit(void *arg){ printf("%s\n",(char*)arg); return NULL; } int main(void){ pthread_t tid; //创建新的线程 pthread_create(&tid,NULL,doit,"new"); sleep(2);//防止主线程先与新线程结束,主线程休眠2s doit("main"); return 0; }
例:如何验证一个进程具有多个线程。需要获取到进程的pid(getpid(2))和线程的tid(pthread_self(3))
头文件
#include <pthread.h> 函数原型 pthread_t pthread_self(void); 功能: 获取调用线程的id,它的值同pthread_create(3)的第一个参数 参数: 返回值: 总是成功返回线程的ID#include<stdio.h> #include<pthread.h> void *doit(void *arg){ pid_t pid; pthread_t tid; pid=getpid(); tid=pthread_self(); printf(“pid:%d\ntid:%s\n”,pid,tid); printf("%s\n",(char*)arg); return NULL; } int main(void){ pthread_t tid; //创建新的线程 pthread_create(&tid,NULL,doit,"new"); sleep(2);//防止主线程先与新线程结束,主线程休眠2s doit("main"); return 0; }
2、线程退出
return和exit(3)的区别:return只是线程执行函数的结束,代表线程的结束。如果再线程函数中调用exit(3).则将会终止进程中的所有线程,故一般不会再线程中使用eixt(3)。
如果要终止一个线程则使用pthread_exit(3):
头文件:同上
函数原型:
void pthread_exit(void* retval);
功能;终止当前线程
参数:
retval:退出的值存放到retval中。
返回值:
永远不返回
可以使用pthreead_cancel(3)来终止其他线程。
头文件:同上
函数原型:
int pthread_cancel(pthread_t thread);
功能:
终止以恶指定线程
参数:
thread:指定接收cancel请求的线程,即指定要设为canceled状态的线程。
返回值:
成功:0
错误:非0错误码
3,线程的汇合
可以使用pthread_join(3)来使线程汇合,即某一线程阻塞等待另一线程,同时回收资源,以达到汇合目的。此时可以获取到线程的退出状态
头文件:同上
函数原型:
int pthread_join(pthread_t thread,void **retval);
功能:
线程汇合,等待指定的线程终止,如果这个指定的线程已经终止了,那么pthread_join立即返回。
参数:
thread:指定等待的终止线程
*retval:指定线程的退出状态(非NULL),如果这个目标线程是用pthread_cancel(3)进行终止的,那么PTHREAD_CANCELED将被保存到*retval中。
返回值:
成功:0
错误:错误码
4,线程分离
线程创建之后,结束时自动回收,不作汇合,这叫做线程的分离。
线程的分离可以视同pthread_detach(3)
头文件;同上
函数原型:int pthread_detach(pthread_t thread)
功能:
标记thread指定的线程为detached状态,当一个处于detached状态的线程终止的时候,线程的资源将会自动回收到系统,而不是汇合的线程来进行结束。
参数:
thread:指定设置为detached状态的线程id。
返回值:
成功:0
错误:错误码
例:线程的汇合
#include<stdio.h> #include<prhead.h> void* doit1(void *arg){ printf("doit1 return !\n"); return (void*)1 } int main(void){ pthread_t tid; void *ret; //创建一个线程 pthread_create(&tid,NULL,doit1,NULL); //指定汇合的线程 pthread_join(tid,&ret); printf("doit1 exit code%d\n",(int)ret); return 0; }
得到的退出状态就是线程函数的返回值。
例:线程退出
#include<stdio.h> #include<prhead.h> void* doit2(void *arg){ printf("doit1 return !\n"); pthread_exit((void*)2) } int main(void){ pthread_t tid; void *ret; //创建一个线程 pthread_create(&tid,NULL,doit1,NULL); //指定汇合的线程 pthread_join(tid,&ret); printf("doit2 exit code%d\n",(int)ret); return 0; }
#include<stdio.h> #include<prhead.h> void* doit3(void *arg){ while(1) printf("doit3 is running !\n"); } int main(void){ pthread_t tid; void *ret; //创建一个线程 pthread_create(&tid,NULL,doit1,NULL); //给doit3发送终止请求 pthread_cancel(tid); //指定汇合的线程 pthread_join(tid,&ret); printf("doit3 exit code%d\n",(int)ret); return 0; }