【实习笔记】线程安全队列

本文介绍了如何实现一个线程安全的队列,该队列带有高水位标功能。当队列元素数量达到高水位标时,入队操作会被阻塞,直到队列中的元素数量减少。同时,队列的出队、空和满的状态检查也是线程安全的。代码中使用了互斥锁和条件变量来实现这一功能,并通过示例展示了其在多线程环境下的工作原理。
摘要由CSDN通过智能技术生成

题目

实现一个带高水位标的线程安全的队列。
1)当队列中数据数量大于等于高水位标时,阻塞入队的操作
2)当队列中的数据小于高水位标时,入队不受阻塞

代码

ThreadSafetyQueue.h

#pragma once
#include <condition_variable>
#include <mutex>
#include <deque>
template<class T>
class ThreadSafetyQueue
{
public:
	typedef std::unique_lock<std::mutex> TLock;

	//maxCapacity为-1,代表队列无最大限制
	explicit ThreadSafetyQueue(const int maxCapacity = -1) :m_maxCapacity(maxCapacity){}

	size_t size()
	{
		TLock lock(m_mutex);
		return m_list.size();
	}

	void push_back(const T& item)
	{
		TLock lock(m_mutex);
		if (true == hasCapacity())  // 判断有无高水位标,无则可一直push
		{
			while (m_list.size() == m_maxCapacity)
			{
				m_notFull.wait(lock);
			}
		}

		m_list.push_back(item);
		std::cout << item << "进去了" << std::endl;
		m_notEmpty.notify_all();  // 通知其他线程此时队列非空,即可进行pop操作
	}

	T pop()
	{
		TLock lock(m_mutex);
		while (m_list.empty())
		{
			m_notEmpty.wait(lock);
		}

		T temp = *m_list.begin();
		m_list.pop_front();

		m_notFull.notify_all();

		lock.unlock();
		return temp;
	}

	bool empty()
	{
		TLock lock(m_mutex);
		return m_list.empty();
	}

	bool full()
	{
		if (false == hasCapacity)  // 无水位标则一直未满
		{
			return false;
		}

		TLock lock(m_mutex);
		return m_list.size() >= m_maxCapacity;
	}

private:
	bool hasCapacity() const
	{
		return m_maxCapacity > 0;
	}

	typedef std::deque<T> TList;
	TList m_list;

	const int m_maxCapacity;

	std::mutex m_mutex;
	std::condition_variable m_notEmpty;
	std::condition_variable m_notFull;
};

test.cpp

#include <iostream>
#include <thread>
#include <stdio.h>
#include "ThreadSafetyQueue.h"
#include <windows.h>

using namespace std;

typedef ThreadSafetyQueue<int> TQueue;

void produce(TQueue& queue)
{
	const int num = 9;
	for (int i = 0; i < num; ++i)
	{
		queue.push_back(i);
	}
}

void consume(TQueue& queue)
{
	while (false == queue.empty())  //非空 empty返回-1 即等于false 则pop_front
	{
		int tmp = queue.pop();
		cout << tmp << "出来了" << endl;
		Sleep(2000);
	}
}

int main()
{
	TQueue queue(2);
	std::thread t1(produce, std::ref(queue));
	std::thread t2(consume, std::ref(queue));

	t2.join();
	t1.join();
	return 0;
}
代码阅读助力tips

1、thread类的构造函数是使用可变参数模板实现的,也就是说,可以传递任意个参数,第一个参数是线程的入口函数(可调用对象),而后面的若干个参数是该函数的参数。

2、unique_lock提供了lock()和unlock()接口,能记录现在处于上锁还是没上锁状态

3、condition_variable有两个重要的接口,notify_all()和wait(),wait()可以让线程陷入休眠状态,notify_all()唤醒处于wait中的所有条件变量。

实现效果

在这里插入图片描述

知识tips

什么是线程安全
实现线程安全的方法
借鉴代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值