目录
线程
1.基本概念:
线程:线程是一个轻量级的进程,位于进程空间内部,一个进程中可以创建多个线程
2.线程创建:
线程独占栈空间,文本段、数据段和堆区与进程共享
3.线程调度:
与进程调度是一样的
宏观并行,微观串行
4.线程消亡:
与进程消亡是一样的
5.进程和线程的区别:
进程是操作系统资源分配的最小单元
线程是CPU任务调度的最小单元
6.多进程和多线程的优缺点:
效率:多线程 > 多进程
多线程只需在同一进程空间内切换
多进程需要在不同的空间中切换
通信:多线程 > 有进程
线程共享全局变量,可以通过全局变量实现数据通信
进程空间是独立的,没有共享空间,通信实现比较复杂
通信实现:多进程 > 多线程
线程共享空间操作时会引发资源竞争
进程没有共享空间,不存在资源竞争的问题
安全:多进程 > 多线程
一个进程异常不会影响其余进程空间
一个线程异常结束会导致进程异常结束,进程异常结束,该进程内所有线程任务均无法向下执行
线程相关的函数接口
创建: fork pthread_create
退出: exit pthread_exit
回收: wait pthread_join
1.pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
功能:
在该进程中创建一个新的线程
参数:
thread:存放线程ID空间首地址
attr:线程属性空间首地址
start_routine:线程要执行的函数的入口
arg:给线程函数的参数
返回值:
成功返回0
失败返回错误码
编译时加 -lpthread选项 ,要链接pthread。
2.pthread_self
pthread_t pthread_self(void);
功能:
获得调用该函数线程的ID
3.pthread_exit
void pthread_exit(void *retval);
功能:
让调用该函数的线程任务结束
参数:
retval:线程结束的值
4.pthread_join
int pthread_join(pthread_t thread, void **retval);
功能:
回收线程空间
参数:
thread:线程的ID号
retval:存放线程结束状态空间的首地址
返回值:
成功返回0
失败返回错误码
这个函数也会阻塞主函数,等待线程结束回收后在进行运行。
线程分离属性
线程结束后,自动回收线程空间
pthread_attr_init
int pthread_attr_init(pthread_attr_t *attr);
功能:
线程属性初始化
pthread_attr_destroy
int pthread_attr_destroy(pthread_attr_t *attr);
功能:
线程属性销毁
pthread_attr_setdetachstate
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
功能:
设置分离属性
PTHREAD_CREATE_DETACHED 分离属性
PTHREAD_CREATE_JOINABLE 加入属性(默认)
void *
是 C 语言中的一种通用指针类型。它表示一个指向未知类型的指针,也称为“无类型指针”。这意味着它可以指向任何类型的数据,因为它没有指定类型。void *
可以用于在函数中传递任意类型的指针,或者用于从函数中返回指向任意类型的指针。
练习:定义一个学生结构体
struct student
{
char name[32];
char sex;
int age;
int score;
};
创建两个线程,线程1负责从终端接收学生信息
线程2负责将学生信息打印在终端
线程互斥
1.互斥锁:防止资源竞争
所有的参数上下都要加锁解锁。
2.函数接口:
pthread_mutex_init:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
功能:
互斥锁初始化
参数:
mutex:互斥锁空间首地址
attr:互斥锁的属性(默认为NULL)
返回值:
成功返回0
失败返回错误码
pthread_mutex_destroy:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:
互斥锁销毁
参数:
mutex:互斥锁空间首地址
返回值:
成功返回0
失败返回错误码
pthread_mutex_lock:
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:
上锁
pthread_mutex_unlock:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:
解锁
临界资源、临界区
加锁解锁中间的代码称为临界资源、临界区
同一时刻临界资源不能同时执行,只能执行其中一个临界资源代码
4.原子操作:
CPU最小的一次不能被任务调度打断的操作称为原子操作
5.互斥锁只能解决资源竞争的问题,无法同步代码(没有先后执行的顺序关系)
死锁
多线程操作互斥锁,导致多个线程均无法向下执行的状态称为死锁状态简称为死锁
死锁产生的四个必要条件:
1.互斥条件
2.不可剥夺条件
3.请求保持
4.循环等待
避免产生死锁:
1.pthread_mutex_trylock 替代 pthread_mutex_lock
trylock是加不上锁就不会等待,继续做其他事,lock会循环等待
2.加锁顺序保持一致
信号量
信号量是一种资源,可以被初始化、申请、释放、销毁
P操作:申请资源
V操作:释放资源
sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:
初始化信号量
参数:
sem:信号量空间首地址
pshared:
0 一个进程中的所有线程间共享
非0 进程间共享
value:
初始化的值
返回值:
成功返回0
失败返回-1
sem_destroy:
int sem_destroy(sem_t *sem);
功能:
信号量的销毁
参数:
sem:信号量空间首地址
返回值:
成功返回0
失败返回-1
sem_wait:
int sem_wait(sem_t *sem);
功能:
申请信号量
sem_post:
int sem_post(sem_t *sem);
功能:
释放信号量