1. 程式人生 > 其它 >C++通過C庫或互斥和條件變數實現訊號量

C++通過C庫或互斥和條件變數實現訊號量

C++標準庫中並沒有訊號量的實現和封裝,我們可以用C語言提供的`

C++利用互斥和條件變數實現訊號量

訊號量是用來實現對共享資源的同步訪問機制,其使用方法和條件變數類似,都是通過主動等待和主動喚醒來實現的。

C++標準庫中並沒有訊號量的實現和封裝,我們可以用C語言提供的<semaphore.h>

C提供的庫<semaphore.h>詳解和使用

#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;
}