1948 字
10 分钟
Tiny Webserver 线程同步机制封装类

基础知识#

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.html
PV操作是由==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;
}
Tiny Webserver 线程同步机制封装类
https://fuwari.cbba.top/posts/tiny-webserver-线程同步机制封装类/
作者
Chen_Feng
发布于
2023-09-13
许可协议
CC BY-NC-SA 4.0