如何使用以下信号量代码

How to use the following Semaphore code

本文关键字:信号量 代码 何使用      更新时间:2023-10-16

我正在读关于Semaphores的文章。据我所知,信号量只允许一定数量的线程访问特定的资源。我看到了这篇文章,它解释了如何使用条件变量和互斥体创建一个简单的信号量类。易于访问的代码是从链接粘贴到这里的

#include <mutex>
#include <condition_variable>
class Semaphore {
public:
    Semaphore (int count_ = 0)
        : count(count) {}
    inline void notify()
    {
        std::unique_lock<std::mutex> lock(mtx);
        count++;
        cv.notify_one();
    }
    inline void wait()
    {
        std::unique_lock<std::mutex> lock(mtx);
        while(count == 0){
            cv.wait(lock);
        }
        count--;
    }
private:
    std::mutex mtx;
    std::condition_variable cv;
    int count;
};

我的问题是如何使用上面的类使这个方法一次只能访问3个线程

void SomeFunction
{
  ------------------------------> Only 3 threads should be allowed access to this function concurrently
  int a = getSomeValue();
  //Do something useful
  ------------------------------>
}

我想我会做一些类似的事情

   Semaphore s(3);
   void SomeFunction
    {
        s.wait();
        int a = getSomeValue();
       //Do sometning useful
        s.notify();
    }

但是,我不确定什么时候会调用wait()notify()

最好使用RAII习语作为信号量:

class SemaphoreLock
{
public:
    SemaphoreLock(Semaphore& s)
        : _pS(&s)
    {
        _pS->wait();
    }
    ~SemaphoreLock()
    {
        _pS->notify();
    }
private:
    Semaphore* _pS;
};
Semaphore s(3);
void SomeFunction()
{
    SemaphoreLock sl(s);
    // implement the function here
}

如果SemaphoreLock对象是在函数体的最开始声明的,那么wait()将在进入函数时被调用,notify()将在退出函数之前被调用,同样在抛出异常且堆栈展开未终止的情况下也是如此。

一个更好的解决方案是将Semaphore的方法:wait重命名为locknotify重命名为unlock。在这种情况下,可以使用std::lock_guard<Semaphore>来代替自写的SemaphoreLock类。