1、进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
2、特性:
3、进程的几种状态
4、进程的上下文:操作系统为运行进程设置的相应的运行环境和进程的实体,组成:
5、进程调度算法
在这些调度算法中,有抢占式和非抢占式的区别。
线程,也被称为轻量级进程(Lightweight Process,LWP),CPU调度和执行的基本单位,它被包含在进程之中,是进程中的实际运作单位。每一个进程都至少有一个线程,一个进程可以有多个线程,可以并发执行,线程依赖于进程而存在,多线程共享该进程拥有的所有资源。线程由线程ID,当前程序计数器(PC),寄存器集合和堆栈组成。
1、同步与互斥
同步:多个进程因为合作完成一个任务产生的同步关系,直接制约关系,使得进程有一定的先后执行关系。
互斥:对资源的共享引起的互斥关系,间接制约关系,多个进程在同一时刻只有一个进程能进入临界区。
临界资源:一次仅允许一个进程使用的系统中的一些共享资源
2、进程间同步的方式--信号量
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
1、信号量
2、互斥量(互斥锁)
3、读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
4、条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
5、临界区,在任意时刻 只允许一个线程对共享资源进行访问,互斥量、信号量可以跨进程使用,临界区只能在进程内部使用。
6、全局变量、静态变量
一组进程在执行过程中,每个进程都在等待其他进程所占有的资源而造成了互相等待,此时系统产生了死锁
1、四个必要条件:
(1)互斥条件:每个资源都是不可共享的
(2)请求保持条件:进程因请求资源而阻塞时,而且该进程不会释放已经占有的资源;
(3)不可剥夺条件:进程已获得的资源,不可被其他进程剥夺;
(4)环路等待条件:多进程之间形成一个循环的等待关系链。
2、原因:系统资源不足或推进顺序不当,导致对不可剥夺资源的不合理分配
3、死锁的预防
破坏四个必要条件之一:
4、死锁的避免
银行家算法:在资源分配之前系统预先判断此次分配是否会导致系统进入不安全状态,如果判断结果为安全,则给该进程分配资源,否则不分配资源,申请资源的进程将阻塞。
5、死锁的检测与恢复
定期启动一个软件检测系统的状态,若发现有死锁存在,则采取措施恢复之。
检测:系统进程资源图的方式检测环路
恢复:故障终止进程、资源剥夺
多线程最难的地方其实在于线程之间的数据共享和同步
C/C++ 多线程 pthread 库相关函数说明
pthread_t 线程结构体
1、调用 pthread_create()函数就可以创建一个线程。它的函数原型如下:
#include <pthread.h>
extern int pthread_create (pthread_t *__restrict __newthread,
const pthread_attr_t *__restrict __attr,
void *(*__start_routine) (void *),
void *__restrict __arg)
pthread.h 是它的库。
参数说明:
第一个参数是 pthread_t* 也就是代表线程实体的指针
第二个参数为了设置线程的属性,一般为 NULL
第三个参数是线程运行时的函数,这是个函数指针。
第四个参数也是一个指针,它是用来将数据传递进线程的运行函数
pthread_join用来等待一个线程的结束,主线程阻塞等待子线程结束,然后回收子线程资源
pthread_detach()即主线程与子线程分离,子线程结束后,资源自动回收
https://blog.csdn.net/weibo1230123/article/details/81410241
pthread_mutex_t 互斥锁
pthread_mutex_lock
pthread_mutex_unlock
pthread_cond_t 条件变量
条件变量是利用线程间共享的全局变量,进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
而条件变量则通过允许线程阻塞并等待另一个线程发送唤醒信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。
/**
* 使用__cond_attr初始化条件变量,__cond_attr设置为NULL,将使用默认属性初始化条件变量。
* @param __cond 要初始化的条件变量
* @param __cond_attr 属性
* @return 如果成功返回0,失败返回错误码
*/
int pthread_cond_init (pthread_cond_t *__cond,
const pthread_condattr_t *__cond_attr);
/**
* 催毁条件变量。
* @param __cond 要催毁的条件变量
* @return 如果成功返回0,失败返回错误码
*/
int pthread_cond_destroy (pthread_cond_t *__cond);
/**
* 唤醒一个用条件变量__cond等待的线程。
* @param __cond 目标条件变量
* @return 如果成功返回0,失败返回错误码
*/
int pthread_cond_signal (pthread_cond_t *__cond);
/* Wake up all threads waiting for condition variables COND. */
/**
* 唤醒所有用条件变量__cond等待的线程。
* @param __cond 目标条件变量
* @return 如果成功返回0,失败返回错误码
*/
int pthread_cond_broadcast (pthread_cond_t *__cond);
/**
* 等待条件变量__cond的一个信号或者广播。调用该函数之前你应该确保已经用
* __mutex上锁。
* @param __cond 目标条件变量
* @param __mutex 配合__cond的锁
* @return 如果成功返回0,失败返回错误码
*/
int pthread_cond_wait (pthread_cond_t * __cond,
pthread_mutex_t * __mutex);
/**
* 在指定时间内等待条件变量__cond的一个信号或者广播,调用该函数之前你应该确保已经用
* __mutex上锁。
* @param __cond 目标条件变量
* @param __mutex 配合__cond的锁
* @param __abstime 绝对时间
* @return
*/
int pthread_cond_timedwait (pthread_cond_t * __cond,
pthread_mutex_t * __mutex,
const struct timespec * __abstime);
进入等待状态前应该先上锁pthread_mutex_lock,pthread_cond_wait/pthread_cond_timedwait内部会自动解锁,但在返回前,函数内部一定会自动重新上锁。然后pthread_mutex_unlock
为了防止“虚假唤醒”,该函数一般放在while循环体中。例如
pthread_mutex_lock(mutex);//加互斥锁
while(条件不成立)//当前线程中条件变量不成立
{
pthread_cond_wait(cond, mutex);//解锁,其他线程使条件成立发送信号,加锁。
}
...//对进程之间的共享资源进行操作
pthread_mutex_unlock(mutex);//释放互斥锁
为什么要配合互斥锁使用?
pthread_cond_wait()需要传入一个已经加锁的互斥锁,该函数把调用线程加入等待条件的调用列表中,然后释放互斥锁,在条件满足从而离开pthread_cond_wait()时,mutex将被重新加锁。
也就是说条件变量本身就是一个竞争资源,所以用一个mutex来保证: 对于某个cond的包括(判断,修改)在内的任何有关操作某一时刻只有一个线程在访问
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。