C++自制简易semaphore信号量

        为方便操作系统进程同步与互斥内容的学习,写了一个简易的semaphore类。

#pragma once
#include <mutex>
#include <sstream>

class Semaphore { //信号量类

	int _count; //信号量初始值, 为1等价于mutex, 为0可实现同步, 大于零可实现多资源的同步
	std::string _name; //信号量的名字,便于打印调试
	std::mutex _mutex;
	std::condition_variable _condition;

public:
	Semaphore(int value, std::string name = "null") : _count(value), _name(name) {}

	friend void P(Semaphore& S) { //wait操作
		std::unique_lock<std::mutex> lock(S._mutex);
		S._count--;
		if (S._count < 0) {
			S._condition.wait(lock);
		}
	}
	friend void V(Semaphore& S) { //signal操作
		std::lock_guard<std::mutex> lock(S._mutex);
		S._count++;
		if (S._count <= 0) {
			S._condition.notify_one();
		}
	}
	std::string inf() { //返回一个含有信号量信息的字符串,调试用
		std::stringstream ss;
		ss << _name << ":" << _count << ' ';
		return ss.str();
	}
};

使用方法:

创建信号量:

        Semaphore S(1); //括号里面第一个参数是信号量初始值,第二是信号量名(可以不写)

        Semaphore S(0, "mutex");

可像操作系统书上一样创建了信号量后直接P、V操作,更加接近教材。

        P(S);

        V(S);

调用inf()方法可返回一个信号量信息的字符串,用来出错调试 

        cout << S.inf();



        而有时想让子线程用detach方式与父线程分离,但是又想父线程在所有子线程执行完毕后再退出。如果用上面的信号量也能实现,假设一个父线程要等待n个子线程执行完毕后才能结束,令初始信号量为0,在每一个子线程结束前做一个V(S)操作,在父进程结束前做n个P(S)操作即可。但这样会频繁的进行唤醒操作,代码写起来也比较繁琐。下面我写了一个专门用来实现等待所有子线程都完成的信号量:

#include <mutex>
#include <sstream>

class Semaphore_finish { //所有任务完成信号量

	int _count; //要完成任务总数
	std::string _name; //信号量名称
	std::mutex _mutex;
	std::condition_variable _condition;

public:
	Semaphore_finish(int value, std::string name = "null") : _count(value), _name(name) {}

	friend void WaitFinish(Semaphore_finish& S) { 
//若所有任务没有完成该函数将被阻塞直到所有任务完成
		std::unique_lock<std::mutex> lock(S._mutex);
		if (S._count > 0) {
			S._condition.wait(lock);
		}
	}
	friend void Release(Semaphore_finish& S) { 
//完成一个任务就释放掉一个count,当所有任务完成时就解锁所有等待所有任务完成的线程
		std::lock_guard<std::mutex> lock(S._mutex);
		S._count--;
		if (S._count == 0) {
			S._condition.notify_all();
		}
	}
	std::string inf() {
		std::stringstream ss;
		ss << _name << ":" << _count << ' ';
		return ss.str();
	}
};

使用时,若有n个等待完成的子线程,就创建对象Semaphore_finish S(n);,只需在每个子线程最后加一个Release(S),在父线程最后加一个WaitFinish(S)就可达到目标,并且只会在所有子线程完成后才进行一次唤醒,效率更高。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值