基础知识
1.RAII
RAII全称是“()”,直译过来就是“()”.
构造函数会()资源 ,析构函数会()资源 。而C++ 的语言机制又保证了,当一个对象创建时会() ,当一个对象超出作用域时会()。那么在RAII的指导下,我们就应该使用()来(),将资源与()的()进行绑定
RAII的核心思想就是将()或者()与对象的生命周期进行绑定,通过C++ 的语言机制,实现资源与状态的() ,()就是RAII最好的例子
1
1
1
1
1
RAII全称是“==Resource Acquisition is Initialization== ”,直译过来就是“==资源获取即初始化== ”.
构造函数会==申请分配==资源 ,析构函数会==释放==资源 。而C++ 的语言机制又保证了,当一个对象创建时会==自动调用构造函数== ,当一个对象超出作用域时会==自动调用析构函数==。那么在RAII的指导下,我们就应该使用==类==来==管理资源== ,将资源与==对象==的==生命周期==进行绑定
RAII的核心思想就是将==资源==或者==状态==与对象的生命周期进行绑定,通过C++ 的语言机制,实现资源与状态的==安全管理== ,==智能指针==就是RAII最好的例子
2.信号量
信号量是一种特殊的(),它只能取()并且只支持():()和().
p操作(wait):()一个单位资源,进程() v操作(signal):()一个单位资源,进程()
假设有信号量SV,对其的P、V操作如下:
P,如果(),则将其();若(),则()(该进程进入等待队列尾部?)
V,如果有其他进程因为等待SV而挂起,则()(()等待队列中队首的等待信号量的进程?);若没有,则将SV()
信号量的取值可以是任何(),最常用的,最简单的信号量是(),只有().
sem_init()函数用于初始化一个()的信号量
sem_destory()函数用于()信号量
sem_wait()函数将以()将信号量(),信号量为()时,sem_wait()()
sem_post()函数以()将信号量(),信号量()时,()调用sem_post()的线程
以上,成功返回(),失败返回()
1
1
1
1
1
信号量是一种特殊的==变量==,它只能取==自然数值==并且只支持==两种操作==:==p操作(wait)==和==v操作(signal)==.
p操作(wait):==申请==一个单位资源,进程==进入== v操作(signal):==释放==一个单位资源,进程==出来==
假设有信号量SV,对其的P、V操作如下:
P,如果==SV>0==,则将其==减一==;若==SV=0==,则==挂起==(该进程进入等待队列尾部?)
V,如果有其他进程因为等待SV而挂起,则==唤醒==(==唤醒==等待队列中队首的等待信号量的进程?);若没有,则将SV==值加一==
// 信号量这里网上的文章一个人一个说法,也不知道哪个对,有人说信号量不能小于0,有人说可以小于0,这个web server中是不能小于0的版本,先按这个记,但是能小于0这个感觉也挺合理,先记在这里,以后问问信号量 https://www.cnblogs.com/graceting/p/3677758.htmlPV操作是由==P操作原语==和==V操作原语==组成(==原语是不可能中断的过程==),操作对象是==信号量S(semaphore)==。具体的: P:① 将信号量S的值==减1==;② 如果==S<0==,则进程进入==等待队列的尾部==,进程变为==等待状态==;否则该进程继续执行 V:① 将信号量S的值==加1==;② 如果==S<=0==,则==唤醒==等待队列中==第一个等待信号量==的进程;否则该进程继续执行。(因为将信号量加1后仍然不大于0,则表示==等待队列中有阻塞的进程==。) **p操作和v操作定义如下:**procedure p(var s:samephore);{ s.value=s.value-1; if (s.value<0) asleep(s.queue);}procedure v(var s:samephore);{ s.value=s.value+1; if (s.value<=0) wakeup(s.queue);}
信号量的取值可以是任何==自然数==,最常用的,最简单的信号量是==二进制信号量==,只有==0和1两个值==.
sem_init()函数用于初始化一个==未命名==的信号量
sem_destory()函数用于==销毁==信号量
sem_wait()函数将以==原子操作方式==将信号量==减一==,信号量为==0==时,sem_wait()==阻塞==
sem_post()函数以==原子操作方式==将信号量==加一==,信号量==大于0==时,==唤醒==调用sem_post()的线程
以上,成功返回==0==,失败返回==errno==
3.互斥锁
互斥锁,也称互斥量,可以(),以确保()访问.当进入关键代码段,();离开关键代码段,().
pthread_mutex_init函数用于()互斥锁
pthread_mutex_destory函数用于()互斥锁
pthread_mutex_lock函数以()给互斥锁()
pthread_mutex_unlock函数以()给互斥锁()
以上,成功返回0,失败返回errno
1
1
1
1
1
互斥锁,也称互斥量,可以==保护关键代码段==,以确保==独占式==访问.当进入关键代码段,==获得互斥锁将其加锁==;离开关键代码段,==唤醒等待该互斥锁的线程==.
pthread_mutex_init函数用于==初始化==互斥锁
pthread_mutex_destory函数用于==销毁==互斥锁
pthread_mutex_lock函数以==原子操作方式==给互斥锁==加锁==
pthread_mutex_unlock函数以==原子操作方式==给互斥锁==解锁==
以上,成功返回0,失败返回errno
4.条件变量
条件变量提供了一种(),当某个共享数据达到()时,()等待这个共享数据的().
pthread_cond_init函数用于初始化条件变量
pthread_cond_destory函数销毁条件变量
pthread_cond_broadcast函数以()的方式唤醒()等待目标条件变量的()
pthread_cond_wait函数用于()目标条件变量.该函数调用时需要传入() ,函数执行时,先把调用这个函数的()放入条件变量的(),然后将互斥锁mutex(),当函数成功返回为()时,互斥锁会再次被(). 也就是说().
1
1
1
1
1
条件变量提供了一种==线程间的通知机制==,当某个共享数据达到==某个值==时,==唤醒==等待这个共享数据的==线程==.
pthread_cond_init函数用于初始化条件变量
pthread_cond_destory函数销毁条件变量
pthread_cond_broadcast函数以==广播==的方式唤醒==所有==等待目标条件变量的==线程==
pthread_cond_wait函数用于==等待==目标条件变量.该函数调用时需要传入== mutex参数(加锁的互斥锁)== ,函数执行时,先把调用这个函数的==线程==放入条件变量的==请求队列==,然后将互斥锁mutex==解锁==,当函数成功返回为==0==时,互斥锁会再次被==锁上==. 也就是说==函数内部会有一次解锁和加锁操作==.
功能
5.锁机制的功能
实现(),通过锁机制,确保().
1
1
1
1
1
实现==多线程同步==,通过锁机制,确保==任一时刻只能有一个线程能进入关键代码段==.
6.封装的功能
类中主要是()进行封装,将锁的()与()函数封装在类的构造与析构函数中,实现()机制
1
1
1
1
1
类中主要是==Linux下三种锁==进行封装,将锁的==创建==与==销毁==函数封装在类的构造与析构函数中,实现==RAII==机制
#include <semaphore.h>// Linux 编程使用信号量相关函数需要引入头文件 <semaphore.h>
class sem {public: // 构造函数 sem() { // 信号量初始化 if (sem_init(&m_sem, 0, 0) != 0) { throw std::exception(); } }
// 析构函数 ~sem() { // 信号量销毁 sem_destroy(&m_sem); }private: sem_t m_sem;};
将重复使用的代码封装为函数,减少代码的重复,使其更简洁
#include <semaphore.h>// Linux 编程使用信号量相关函数需要引入头文件 <semaphore.h>
// 条件变量的使用机制需要配合锁来使用// 内部会有一次加锁和解锁// 封装起来会使得更加简洁bool wait() { int ret = 0; pthread_mutex_lock(&m_mutex); ret = pthread_cond_wait(&m_cond, &m_mutex); pthread_mutex_unlock(&m_mutex); return ret == 0;}
bool signal() { return pthread_cond_signal(&m_cond) == 0;}