信号量是一种特殊的变量,它只能取自然数值并且只支持两种操作:等待(P)和信号(V).假设有信号量SV,对其的P、V操作如下:

  • P,如果SV的值大于0,则将其减一;若SV的值为0,则挂起执行
  • V,如果有其他进行因为等待SV而挂起,则唤醒;若没有,则将SV值加一

int sem_init(sem_t *sem, int pshared, unsigned int value)

初始化m_sem value为指定信号量的初始值

  • pshared为0 信号量在进程的线程之间共享
  • pshared非0 信号量在进程之间共享

sem_init函数用于初始化一个未命名的信号量
sem_destory函数用于销毁信号量
sem_wait函数将以原子操作方式将信号量减一,信号量为0时,sem_wait阻塞
sem_post函数以原子操作方式将信号量加一,信号量大于0时,唤醒调用sem_post的线程

调用seminit函数时,操作系统将创建信号量对象,此对象中记录着“信号量值”(semaphoreValue)整数。
该值在调用sem_post函数时增1,调用semwait函数时减1。
但信号量的值不能小于0,因此,在信号量为0的情况下调用sem一vait函数时,调用函数的线程将进人阻塞状态(因为函数未返回)。
当然,此时如果有其他线程调用sem一post函数,信号量的值将变为1,而原本阻塞的线程可以将该信号量重新减为0并跳出阻塞状态。
实际上就是通过这种特性完成临界区的同步操作,可以通过如下形式同步临界区(假设信号量的初始值为1)。

**类中主要是Linux下三种锁进行封装,将锁的创建于销毁函数封装在类的构造与析构函数中,实现RAII机制

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;
};

Reference:

https://blog.csdn.net/m0_45867846/article/details/109021863