C++实现信号量

背景
实现
代码toc

背景

信号量与条件变量差异对比

  • 信号量存在一个计数,可以反映出当前阻塞在wait上的线程数(值小于0),或下次wait不会阻塞的线程数;条件变量没有相应计数
  • 信号量仅能递增或递减计数,信号量每次递增只能唤醒一个阻塞线程;条件变量存在广播操作,能一次性唤醒所有阻塞线程
  • 信号量计数可以被初始化为大于0的数n,代表可访问资源个数,在后续访问时wait时,n个线程均不会阻塞,可同时访问资源;条件变量初始化后,执行wait的线程将全部阻塞,直到收到通知
  • 信号量递增一次,便会多一个wait不阻塞的线程数(不存在阻塞线程时);对于条件变量,当没有线程阻塞在wait时,发出的唤醒信号将被丢弃,导致先发出唤醒信号,随后wait将仍被阻塞,即所谓的唤醒丢失
  • 信号量不存在虚假唤醒问题;条件变量存在虚假唤醒
  • 信号量可单独使用;条件变量必须需配合mutex一起使用

C++标准库仅有条件变量,而没有信号量,下面实现一个跨平台信号量

实现

信号量最基本的操作有三个

  • 初始化决定了wait后可立即执行线程数
  • 递减操作SemWait,该操作使信号量减1,如果减1后变为负数,线程会阻塞在SemWait上,否则继续执行
  • 递增操作SemSignal,该操作使信号量加1,如果加1后大于等于0,阻塞在SemWait上的线程被唤醒

代码

#pragma once
#include <mutex>
#include <condition_variable>

class Semaphore final{
public:
    explicit Semaphore(int iCount = 0);
    ~Semaphore();

    void Signal();
    void Wait();
    int GetValue();

    Semaphore(const Semaphore& rhs) = delete;
    Semaphore(Semaphore&& rhs) = delete;
    Semaphore& operator=(const Semaphore& rhs) = delete;
    Semaphore& operator=(Semaphore&& rhs) = delete;

private:
    std::mutex m_mLock;
    std::condition_variable m_cConditionVariable;
    int m_iCount;
};
#include "Semaphore.h"

Semaphore::Semaphore(int iCount) : m_iCount(iCount){
}

Semaphore::~Semaphore(){
}

void Semaphore::Signal(){
    std::unique_lock<std::mutex> lock(m_mLock);
    if(++m_iCount >= 0){
        m_cConditionVariable.notify_one();
    }
}

void Semaphore::Wait(){
    std::unique_lock<std::mutex> lock(m_mLock);
    --m_iCount;
    m_cConditionVariable.wait(lock, [this] { return m_iCount >= 0; });
}

int Semaphore::GetValue(){
    std::unique_lock<std::mutex> lock(m_mLock);
    return m_iCount;
}


来自为知笔记(Wiz)

上一篇:C语言10.0


下一篇:b_hw/pdd_任务最大得分(堆/multiset)