线程概述
概念
进程与线程的区别
- 进程间难以共享,线程可共享
- 创建进程代价高,线程代价低
线程和进程的虚拟地址空间
线程之间共享与非共享资源
NPTL 有关介绍
线程操作函数
创建线程—— pthread_create函数
- 一般情况下,main函数所在的线程我们称之为主线程(main线程),其余创建的线程
称之为子线程。 - 程序中默认只有一个进程,fork()函数调用,2个进程
- 程序中默认只有一个线程,pthread_create()函数调用,2个线程。
#include
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
- 功能:创建一个子线程
- 参数:
thread:传出参数,线程创建成功后,子线程的线程ID被写到该变量中。
attr : 设置线程的属性,一般使用默认值,NULL
start_routine : 函数指针,这个函数是子线程需要处理的逻辑代码
arg : 给第三个参数使用,传参 - 返回值:
成功:0
失败:返回错误号。这个错误号和之前errno不太一样。
获取错误号的信息: 在 #include 下的
char * strerror(int errnum);
示例代码
- 注意传入参数的数据类型 void*
- 休眠1s 是为了 防止程序过快结束,子线程还为创建调用成功,或者 sleep(1);//可以改为 pthread_exit() 函数 终止主进程
- 注意gcc编译链接过程中的语句 后缀要加个 -pthread或者-lpthread ,(静态库、动态库中的概念)
#include
#include
#include
#include
void * myCallback(void * arg) {
printf("I am Child thread..n");
printf("recv:%dn",*(int *)arg);//注意数据类型
return arg;
}
int main() {
pthread_t pthreadID;
int num =10;//用于测试pthread_create 最后一个形参,传递参数
//创建子线程
int ret = pthread_create(&pthreadID,NULL,myCallback,&num);
if(ret == -1) {
int _errno;
char * errstr = strerror(_errno);
printf("erroinfo:%s",errstr);
}
//主线程打印 1~10
for(int i = 0 ;i<10;i++) {
printf("%dn",i);
}
//休眠1s 用于 子线程创建,然后调用回调函数
sleep(1);//可以改为 pthread_exit() 函数 终止主进程
return 0;
}
终止线程—— pthread_exit() 函数
#include
void pthread_exit(void *retval);
- 功能:终止一个线程,在哪个线程中调用,就表示终止哪个线程
- 参数:
retval:需要传递一个指针,作为一个返回值,可以在pthread_join()中获取到。
获取线程ID—— pthread_self() 函数
pthread_t pthread_self(void);
比较线程ID(多用于跨平台)—— pthread_equal() 函数
- int pthread_equal(pthread_t t1, pthread_t t2);
功能:比较两个线程ID是否相等 - 不同的操作系统,pthread_t类型的实现不一样,有的是无符号的长整型,有的
是使用结构体去实现的。
连接已终止线程 pthread_join()函数
#include
int pthread_join(pthread_t thread, void **retval);
- 功能:和一个已经终止的线程进行连接
回收子线程的资源
这个函数是阻塞函数,调用一次只能回收一个子线程
一般在主线程中使用 - 参数:
thread:需要回收的子线程的ID
retval: (注意是void**)接收子线程退出时的返回值(就是pthread_exit(void *retval) 中的retval) - 返回值:
0 : 成功
非0 : 失败,返回的错误号 - 为什么是 void *? 这样可以修改 int ,详见:探讨pthread_join 第二参数是void**.
分离线程 pthread_detach()
#include
int pthread_detach(pthread_t thread);
- 功能:分离一个线程。被分离的线程在终止的时候,会自动释放资源返回给系统。
1.不能多次分离,会产生不可预料的行为。
2.不能去连接一个已经分离的线程,会报错。 - 参数:需要分离的线程的ID
- 返回值:
成功:0
失败:返回错误号