【C++代码】信号量Semaphore

    科技2022-08-15  101

            C++11中并没有信号量Semaphore的库 让我们直接调用,但我们可以用C++11中提供的mutex和condition_variable来自己实现一个Semaphore类。

           

           

    C++代码如下:

    #include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; // 如果不写这句,后面的mutex、cout等前面都要加std:: class Semaphore { private: int count; mutex m; condition_variable cv; public: Semaphore(int count_) : count(count_) {} // p操作:count 减1,如果count<0,则资源不足,把线程放入阻塞队列 void p() { unique_lock<mutex> loc(m); // if (--count < 0) { cv.wait(loc); } } // v操作:count加1,如果 count <= 0 ,则有线程阻塞,在阻塞队列里唤醒一个线程 void v() { unique_lock<mutex> loc(m); if (++count <= 0) { cv.notify_one(); } } };

           

           

    如何使用信号量?

            总结起来就是一句话:先v后p         在期望先执行的代码后执行v操作,在期望后执行的代码前执行p操作。        

    举个例子

            不管两个线程谁先执行,我们都希望让线程先打印first,后打印second,如何让这两个线程按序打印呢?         按照前面说的,我们只需要在first函数(期望先执行的代码)里写上v操作,在second函数(期望后执行的代码)里写上p操作,就能实现两个线程的同步了。

    Semaphore s(0); // 信号量初始化count为0 void first() { cout << "first" << endl; // 期望先执行的代码 s.v(); // 期望先执行的代码 后面 写上v } void second() { s.p(); // 期望后执行的代码 前面写上p cout << "second" << endl; // 期望后执行的代码 } int main() { thread t2(second); thread t1(first); t2.detach(); t1.detach(); this_thread::sleep_for(chrono::milliseconds(500)); }

            我们可以来分析一下上面的程序:

    情况1: 如果先执行t1线程,在打印完first后,信号量s中的count加1,此时count=1。然后执行到t2线程,此时count减1,count=0,但并未<0,因此不会被阻塞,顺利打印second。情况2: 如果先执行t2线程,信号量s中的count减1,此时count=-1,<0,线程t2被阻塞。然后t1线程打印first,信号量s中的count加1,此时count=0,满足<=0条件,阻塞队列中的t2会被唤醒,继续执行,打印second。

           

           

    Processed: 0.030, SQL: 8