1. 源码奉上
Sem_thread.h:
#pragma once
#include<iostream>
#include<mutex>
#include<condition_variable>
using namespace std;
class Sem_thread
{
private:
//信号量的值,大于0表示该类资源还有_count个,无陷入阻塞的线程;反之则有|_count|个线程陷入阻塞
long _count;
//互斥锁mutex;用于对临界资源的互斥访问
std::mutex _mutex;
//条件变量;用于将线程挂起、唤醒
std::condition_variable _cond;
public:
//构造函数——初始化该信号量对象的值,默认为0
Sem_thread(int count=0)
:_count(count)
{ }
//P操作
void P()
{
unique_lock<mutex> ulock(_mutex);
//P操作后,若此时信号量的的值 < 0 即表示此时无该类资源,此线程陷入阻塞挂在等待队列
if (--_count < 0)
{
//wait()两步: 1.阻塞当前线程 2.释放锁unlock
_cond.wait(ulock);
}
}
//V操作
void V()
{
unique_lock<mutex> ulock(_mutex);
//v操作后,若此时信号量的的值 <= 0 即表示此时有进程陷入阻塞挂在等待队列,故唤醒一个
if (++_count <= 0)
{
_cond.notify_one();
}
}
};
2. 示例
2.1 源码如下:
三个线程分别打印A、B、 C; 现要求必须按照ABCABCABC……这样的顺序打印(这里以打印5组为例)
#include"Sem_thread.h"
#include<thread>
Sem_thread SemA(1);
Sem_thread SemB;
Sem_thread SemC;
void Show_A()
{
for (int i = 0; i < 5; i++)
{
SemA.P();
cout << "A ";
SemB.V();
}
}
void Show_B()
{
for (int i = 0; i < 5; i++)
{
SemB.P();
cout << "B ";
SemC.V();
}
}
void Show_C()
{
for (int i = 0; i < 5; i++)
{
SemC.P();
cout << "C" << endl;
SemA.V();
}
}
int main()
{
thread tha(Show_A);
thread thb(Show_B);
thread thc(Show_C);
tha.join();
thb.join();
thc.join();
return 0;
}