如何优雅的退出线程(condition_variable )

C++多线程并发编程入门(目录)

使用条件变量来实现在析构函数中再次向线程发出一次notify,之后join 线程,等等线程安全退出。

#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <string_view>
#include <mutex>
#include <queue>
#include <sstream>

using namespace std;
class Logger
{
public:
	Logger();
	virtual ~Logger();
	Logger(const Logger& src) = delete;
	Logger& operator=(const Logger& rhs) = delete;
	void log(std::string entry);
private:
	void processLogging();
	std::mutex m_mutex;
	std::condition_variable m_condition_var;
	std::queue<std::string> m_queue;
	std::thread m_thread;
	bool m_have_to_exit = false;
};
Logger::Logger()
{
	m_thread = thread{ &Logger::processLogging, this };
	cout << "Logger::Logger()" << endl;
}

void Logger::log(std::string entry)
{
	unique_lock<std::mutex> lock(m_mutex);
	m_queue.push(entry);
	m_condition_var.notify_all();
}

Logger::~Logger()
{
	cout << "Logger::~Logger()" << endl;
	{
		unique_lock<std::mutex> lock(m_mutex);
		m_have_to_exit = true;
		m_condition_var.notify_all();
	}
	m_thread.join();//这一句不能被lock控制,否则退不出去
}

void Logger::processLogging()
{
	cout << "Logger::processLogging() begin run...." << endl;
	ofstream logFile("log.txt");

	if (logFile.fail())
	{
		cerr << "Failed to open logfile." << endl;
		return;
	}

	unique_lock<std::mutex> lock(m_mutex);
	while (true)
	{
		if (!m_have_to_exit)
		{
			m_condition_var.wait(lock); 
		}
		lock.unlock();
		while (true)//循环处理队列直到为空
		{
			lock.lock();
			if (m_queue.empty())
			{
				break;
			}
			else
			{
				logFile << m_queue.front() << endl;
				m_queue.pop();
			}
			lock.unlock();
		}
		if (m_have_to_exit)
		{
			cout << "m_have_to_exit is true.\n";
			break;
		}
	}
	cout << "Logger::processLogging() exited." << endl;
}

void logSomeMessage(int id, Logger& logger)
{
	for (int i = 0; i < 5; ++i)
	{
		stringstream ss;
		ss << " Thread " << id<< " log message the " << i <<"th times.";
		logger.log(ss.str());
	}
}

int main()
{
	cout << "hello main.\n";
	Logger logger;
	cout << "ready to create producer" << endl;
	vector<thread> threads;
	for (int i = 0; i < 5; ++i)
	{
		cout << "times: " << i << "\n";
		threads.emplace_back(logSomeMessage, i, ref(logger));
	}
	for (auto& t : threads)
	{
		t.join();
	}
	cout << "main exited.\n";
	return 0;
}

程序输出:

文件输出:

 Thread 1 log message the 0th times.
 Thread 0 log message the 0th times.
 Thread 1 log message the 1th times.
 Thread 2 log message the 0th times.
 Thread 0 log message the 1th times.
 Thread 1 log message the 2th times.
 Thread 2 log message the 1th times.
 Thread 0 log message the 2th times.
 Thread 1 log message the 3th times.
 Thread 2 log message the 2th times.
 Thread 0 log message the 3th times.
 Thread 1 log message the 4th times.
 Thread 2 log message the 3th times.
 Thread 0 log message the 4th times.
 Thread 2 log message the 4th times.
 Thread 4 log message the 0th times.
 Thread 3 log message the 0th times.
 Thread 3 log message the 1th times.
 Thread 4 log message the 1th times.
 Thread 3 log message the 2th times.
 Thread 4 log message the 2th times.
 Thread 3 log message the 3th times.
 Thread 4 log message the 3th times.
 Thread 3 log message the 4th times.
 Thread 4 log message the 4th times.

参考:如何优雅地退出线程?_std::thread exit_帮主写书的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值