C++通过C库或互斥和条件变量实现信号量
C++利用互斥和条件变量实现信号量
信号量是用来实现对共享资源的同步访问机制,其使用方法和条件变量类似,都是通过主动等待和主动唤醒来实现的。
C++标准库中并没有信号量的实现和封装,我们可以用C语言提供的<semaphore.h>库
C提供的库<semaphore.h>详解和使用
一、函数简介
信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init()用来初始化一个信号量。它的原型为:
extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。
(1)函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
(2)函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
(3)函数sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) 与 sem_wait() 类似,只不过 abs_timeout 指定一个阻塞的时间上限,如果调用因不能立即执行递减而要阻塞。
(4)函数sem_destroy(sem_t *sem)用来释放信号量sem。
#include <semaphore.h> //先引入库
class Foo {
private:
sem_t sem_1, sem_2; //定义需要的信号量
public:
Foo() {
sem_init(&sem_1, 0, 0), sem_init(&sem_2, 0, 0); //初始化信号量
}
void first(function<void()> printFirst) {
printFirst();
sem_post(&sem_1); //v操作,使变量加1
}
void second(function<void()> printSecond) {
sem_wait(&sem_1);
printSecond();
sem_post(&sem_2);
}
void third(function<void()> printThird) {
sem_wait(&sem_2);
printThird();
}
};
互斥和条件变量实现信号量
1、信号量
信号量是一个整数count,提供两个原子(atom,不可分割)操作:P操作和V操作
- P操作(wait操作):count减1;如果 count < 0 那么挂起执行的线程
- V操作(signal操作):count加1;如果 count <= 0 那么唤醒一个执行线程
2、信号量实现(定义一个类)
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
class semaphore
{
public:
semaphore(int value = 1) : count(value) {}
void wait()
{
unique_lock<mutex> lck(mtx);
if (--count < 0) //资源不足挂起线程
cv.wait(lck); //第一次调用时后面第二个参数默认为false,之后为true
}
void signal()
{
unique_lock<mutex> lck(mtx);
if (++count <= 0) //有线程挂起,唤醒一个
cv.notify_one();
}
private:
int count;
mutex mtx;
condition_variable cv;
};
3.利用信号量解决吃水果问题
吃水果问题:桌子有一只盘子,只允许放一个水果,父亲专向盘子放苹果,母亲专向盘子放桔子 儿子专等吃盘子的桔子,女儿专等吃盘子的苹果。只要盘子为空,父亲或母亲就可以向盘子放水果, 仅当盘子有自己需要的水果时,儿子和女儿可从盘子取出。请给出四个人之间的同步关系,并用 pv操作实现四个人的正确活动的问题。
semaphore plate(1), apple(0), orange(0);
void father()
{
while (true) {
plate.wait();
cout << "往盘中放一个苹果" << endl;
apple.signal();
}
}
void mother()
{
while (true) {
plate.wait();
cout << "往盘中放一个橘子" << endl;
orange.signal();
}
}
void son()
{
while (true) {
orange.wait();
cout << "儿子吃橘子" << endl;
plate.signal();
}
}
void daughter()
{
while (true) {
apple.wait();
cout << "女儿吃苹果" << endl;
plate.signal();
}
}
int main()
{
thread f(father), m(mother), s(son), d(daughter);
f.join();
m.join();
s.join();
d.join();
return 0;
}

C++标准库中并没有信号量的实现和封装,我们可以用C语言提供的`
浙公网安备 33010602011771号