C++ 信号量

C++20 新增了对于信号量的支持,具体参考 

https://zh.cppreference.com/w/cpp/thread/counting_semaphore

template< std::ptrdiff_t LeastMaxValue = /* 由实现定义 */ >
class counting_semaphore;

(1)(C++20 起)

using binary_semaphore = std::counting_semaphore<1>;

(2)(C++20 起)

counting_semaphore 是一个轻量同步原语,能控制对共享资源的访问。不同于 std::mutexcounting_semaphore 允许同一资源进行多个并发的访问,至少允许 LeastMaxValue 个同时的访问者

binary_semaphore 是 std::counting_semaphore 的特化的别名,其 LeastMaxValue 为 1。实现可能将 binary_semaphore 实现得比 std::counting_semaphore 的默认实现更高效

在Visual studio中信号量是使用原子锁来实现的

现在使用锁和信号量手动实现一个信号量

#ifndef __SEMAPHORE_H__
#define __SEMAPHORE_H__

#include <condition_variable>
#include <mutex>
#include <assert.h>

template <int maxValue = INT_MAX>
class Semaphore {
private:
	std::mutex m_mtx;
	std::condition_variable m_cv;
	int m_currCount = 0;

public:
	static constexpr int max() {
		return maxValue; //返回允许的最大值
	}

	Semaphore(int initCount) : m_currCount(initCount) {
		assert(initCount >= 0 && initCount <= max()); //initCount 不能大于 maxValue
	}

	~Semaphore() = default;
	Semaphore(const Semaphore&) = delete;
	Semaphore& operator=(const Semaphore&) = delete;

	void release(int update = 1) {
		if (update == 0) {
			return;
		}
		std::unique_lock<std::mutex> lock(m_mtx);
		assert(update >= 0 && update <= max() - m_currCount);

		m_currCount += update;
		if (m_currCount > 0) {
			m_cv.notify_all();
		}
	}

	void acquire() {
		std::unique_lock<std::mutex> lock(m_mtx);
		m_cv.wait(lock, [this]() { return m_currCount > 0; }); //信号量值小于等于零时阻塞
		m_currCount--;
	}

	bool try_acquire() {
		std::unique_lock<std::mutex> lock(m_mtx);
		if (m_currCount <= 0) {
			return false;
		}
		--m_currCount;
		return true;
	}
};

#endif

相关测试用例

#include "semaphore.h"
#include <thread>
#include <iostream>

void test() {
    using BinarySemaphore = Semaphore<1>;  //重命名信号量

	BinarySemaphore binSem{0};

	auto worker = [](BinarySemaphore &binSemaphore) {
		binSemaphore.acquire();
		std::cout << "worker thread is running\n";
	};

	std::thread workerThread(worker, std::ref(binSem));
	std::cout << "main thread is running\n";

	using namespace std::literals;
	std::this_thread::sleep_for(2s);
	
	binSem.release();
	workerThread.join();
}

int main() {
	test();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值