C++实现的线程安全的单例的生产者消费者代码
记录一次失败的面试手撕,写生产者消费者确实太少了,导致没撕出来。
现在手写一下都得写一个来小时,得多熟悉一下
#include<iostream>
#include<vector>
#include<thread>
#include<condition_variable>
#include<mutex>
#include<queue>
#include<chrono>
using namespace std;
int num=0;
struct Task{
int n;
Task(){
n=num++;
}
};
class ThreadSafeQueue{
private:
//重要点:构造函数私有化,拷贝构造和赋值函数delete
ThreadSafeQueue(){}
ThreadSafeQueue(ThreadSafeQueue& t)=delete;
ThreadSafeQueue& operator=(const ThreadSafeQueue& t) = delete;
//在这个单例模式中得有锁,多个线程访问时得保证不冲突
std::mutex mutex_;
std::condition_variable cv_;
//一个存储任务的队列
queue<Task> taskQueue_;
//记录是否终止
bool shutdownFlag_=false;
public:
//获取实例的单例静态函数
static ThreadSafeQueue& get_instance(){
static ThreadSafeQueue instance;//这个得是静态函数内的静态变量,保证全局存在
return instance;
}
//什么时候使用这个获取大小的函数呢?如果是在内部使用的话,就不需要加锁,但是如果在外部的话需要加锁
//加个锁吧,因为内部可以直接用queue的size函数,这个函数是给外部使用的
int getQueueSize(){
std::lock_guard<mutex> lock(mutex_);
//std::unique_lock<mutex> lock(mutex_);
return taskQueue_.size();
}
void put(Task t){
std::lock_guard<mutex> lock(mutex_);
if(shutdownFlag_) return ;
taskQueue_.push(t);
cv_.notify_one();
}
//这里最好是用这种来返回,因为这样的话,内部如果size==0了,也可以进行返回,返回提取失败
bool get(Task& t){
std::unique_lock<mutex> lock(mutex_);
cv_.wait(lock,[this](){
return !taskQueue_.empty()||shutdownFlag_;//如果返回true,就会继续执行,否则进入阻塞
});
if(shutdownFlag_&&taskQueue_.empty()) return false;//如果是空的且要关闭了,就返回false
t=std::move(taskQueue_.front());
taskQueue_.pop();
return true;
}
void shutdown(){
//这个地方可以不加锁吗?
{
std::lock_guard<mutex> lock(mutex_);
shutdownFlag_=true;
}
cv_.notify_all();
}
};
//生产者函数
void producer(int id){
for(int i=0;i<5;++i){
Task t;
ThreadSafeQueue::get_instance().put(t);
cout<<"producer_"<<id<<" produce the "<<t.n<<"\n";
std::this_thread::sleep_for(std::chrono::microseconds(500));
}
}
void consumer(int id){
while(true){
Task t;
bool bResult=ThreadSafeQueue::get_instance().get(t);
if(bResult==false){
cout<<"the End!\n";
break;
}
cout<<"consumer_"<<id<<" consume the "<<t.n<<"\n";
std::this_thread::sleep_for(std::chrono::microseconds(500));
}
}
int main(){
vector<thread> producers;
vector<thread> consumers;
for(int i=0;i<5;++i){
producers.emplace_back(thread(producer,i));
consumers.emplace_back(thread(consumer,i));
}
for(int i=0;i<5;++i){
producers[i].join();
}
ThreadSafeQueue::get_instance().shutdown();
for(int i=0;i<5;++i){
consumers[i].join();
}
return 0;
}
浙公网安备 33010602011771号