线程
概念
线程是一个轻量级的进程,为了提高系统的性能引入线程,线程和进程都参与cpu统一的调度
进程和线程的区别(面试题)
共性:都为操作系统提供了并发执行的能力
不同点:
1.调度和资源上:线程是系统调度的最小单位,进程是资源分配的最小单位。
2.地址空间上:同一个进程创建多个线程共享进程资源,进程的地址空间相互独立。
3.通信方面:线程的通信相对简单,只需要通过全局变量就能实现。但是需要考虑临界资源(临界资源包括同一 个文件,全局变量等)访问的问题,进程间的通信相对复杂,需要借助进程间的通信机制(借助3g-4g的的 内核空间)
4.安全性方面:线程的安全性相对较差,当进程结束时会导致所有线程退出,进程相对于安全。
线程资源
-
共享的资源:可执行的指令,静态的数据,进程中打开的文件描述符,信号处理函数。当前的工作目录,用户的ID,用户的组ID
-
私有资源:线程ID (TID)、PC(程序计数器)和相关寄存器、堆栈、错误号 (errno)、信号掩码和优先级、执行状态和属性
-
线程标识:主线程的 TID 和 PID 是相同的,每个子线程有自己独立的 TID,但它们都共享相同的 PID
线程的函数接口
创建线程(pthread_create)
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
参数:1.pthread_t *thread:线程标识,成功创建线程后,pthread_create 会将新线程的 ID 写入 thread 指向的内存位置。
2.const pthread_attr_t *attr:线程属性, NULL:代表设置默认属性
3. void *(*start_routine):函数名,代表线程函数,指向一个函数的指针,这个函数就是线程的执行体(也就是线程的入口函数)。该函数必须符合 void *(*start_routine)(void *) 的原型,即接受一个 void * 类型的参数,并返回一个 void * 类型的值。
4.void *arg:传递给 start_routine 的参数。arg 是一个通用的指针,可以传递任何类型的数据(通常是一个结构体的指针,以便传递多个参数)。如果不需要传递参数,可以传递 NULL。
返回值:成功返回0
失败返回错误码
函数指针:
本质上指针,指向函数
格式:数据类型 (*函数指针变量)(形参);
数据类型 函数名(参数)
函数指针一般情况下作为函数的参数使用:意思就是在一个函数中回调另一方函数的功能
void hanshu(int a)
void(*p)(int) = hanshu;
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *mypthread(void *arg)
{
printf("子线程执行结束\n");
}
int main(int argc, char const *argv[])
{
//创建线程的唯一标识
pthread_t tid;
//创建线程
if(pthread_create(&tid,NULL,mypthread,NULL))
{
printf("creat err\n");
return -1;
}
printf("主线程执行中。。。\n");
sleep(1);
printf("主线程执行结束\n");
return 0;
}
注意:编译时注意链接线程库
gcc fimename.c -lpthread
线程函数和普通函数的区别
1. 普通函数是顺序执行的,手动调用函数,执行函数操作,线程函数在创建的线程中并发执行,不会影响主程序的运行。
2. 普通函数同步执行,线程函数异步执行
3. 存储位置不一样,普通函数存放在当前线程的栈区空间,线程函数共享进程的全局变量和堆空间。
线程退出(pthread_exit)
void pthread_exit(void *retval);功能:用于执行退出线程
参数:任意类型的数据,一般写NULL
返回值:无
pthread_exit(NULL);
线程资源回收函数
int pthread_join(pthread_t thread, void **retval);
功能:用于等待一个指定的线程结束,阻塞函数
参数:thread:创建的线程对象
void **retval: 指针*retval指向线程返回的参数,一般是NULL
返回值:成功 : 0
失败:errno
int pthread_detach(pthread_t thread);
功能:让线程结束时自动回收线程资源,让线程和主线程分离
参数:thread:线程ID
返回值:成功 : 0
失败:errno
获取线程号(pthread_self)
pthread_t pthread_self(void);
功能:
获取线程号
返回值:
成功:调用此函数线程的ID