什么是线程
- 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是一个进程内部的控制序列。
- 一切进程至少都有一个执行线程。
进程和线程
- 进程是承担分配资源的基本单位,线程是调度的基本单位。
- Linux下线程是轻量级进程。也就是说,Linux下是用进程模拟线程的。每一个用户态线程,在内核中都对应一个调度实体,也拥有自己的进程描述符。
POSIX线程库
- 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_t”打头的。
- 要使用这些库函数,要引入头文件#include <pthread.h>t
- 链接这些库函数时,要使用编译器命令的”-lpthread”选项
功能:创建一个新的线程
函数:int pthread_create(pthread_t* thread, const pthread_attr_t* attr,void* (start_routine) (void ), void *arg);
参数:
thread:返回线程id
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数。
arg:传给线程启动函数的参数。
返回值:成功返回0,失败返回错误码。
创建线程
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
void* rout()
{
while(1)
{
printf("I am thread 1!\n");
sleep(1);
}
}
int main()
{
pthread_t tid;
int ret = pthread_create(&tid,NULL,rout,NULL);
if(ret != 0)
{
perror("create!");
exit(EXIT_FAILURE);
}
while(1)
{
printf("I am main thread!\n");
sleep(1);
}
return 0;
}
线程ID
现在介绍线程ID,不同于pthread_t类型的线程ID,和进程ID一样,线程ID是pid_t类型的变量,而且是用来唯一标示线程的一个整型变量。查看线程ID方法如下:
pthread_create函数会产生一个线程id,存放在第一个参数指向的地址中,该线程id是指用户级线程id。
线程库提供了相关接口,可以用来获得线程自身的id。
pthread_t类型:实质上是一个进程空间上的一个地址。
线程库NPTL提供了一个pthread_self函数,可以获得线程自身的ID
pthread_t pthread_self(void);
线程终止
如果需要只终止某个线程而不终⽌整个进程,可以有三种⽅法:1. 从线程函数return。这种⽅法对主线程不适⽤,从main函数return相当于调⽤exit。
2. 线程可以调⽤pthread_ exit终⽌⾃⼰。
3. ⼀个线程可以调⽤pthread_ cancel终⽌同⼀进程中的另⼀个线程。
pthread_exit函数
功能:线程终⽌
原型
void pthread_exit(void *value_ptr);
参数
value_ptr:value_ptr不要指向⼀个局部变量。
返回值:⽆返回值,跟进程⼀样,线程结束的时候⽆法返回到它的调⽤者(⾃⾝)
需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是⽤malloc分配的,不能在线
程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。
pthread_cancel函数
功能:取消⼀个执⾏中的线程
原型
int pthread_cancel(pthread_t thread);
参数
thread:线程ID
返回值:成功返回0;失败返回错误码
线程等待
为什么需要线程等待?
已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
创建新的线程不会复⽤刚才退出线程的地址空间。
功能:等待线程结束
原型
int pthread_join(pthread_t thread, void **value_ptr);
参数
thread:线程ID
value_ptr:它指向⼀个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码
线程分离
默认情况下,新创建的线程是joinable的,线程退出后,需要对其进⾏pthread_join操作,否则⽆法
释放资源,从而造成系统泄漏。
如果不关心线程的返回值, join是⼀种负担,这个时候,我们可以告诉系统,当线程退出时,⾃动
释放线程资源 。
int pthread_detach(pthread_t thread);
可以是线程组内其他线程对目标线程进⾏分离,也可以是线程⾃⼰分离
:pthread_detach(pthread_self());
joinable和分离是冲突的,⼀个 线程不能既是joinable⼜是分离的 。
void *thread(void* arg)
{
pthread_detach(pthread_self()); //分离自身
printf("%s\n",(char*)arg);
return NULL;
}
int main()
{
int ret = 0;
pthread_t tid;
pthread_create(&tid,NULL,thread,"thread 1 is running!");
sleep(1);
if(pthread_join(tid,NULL) == 0)
{
printf("pthread wait success!\n");
ret = 0;
}
else
{
printf("pthread wait faild!\n");
ret = 1;
}
return ret;
}
运行结果:说明线程分离后不能被等待