C++多线程学习(九、不安全的队列测试,简单封装线程安全队列)

这篇具有很好参考价值的文章主要介绍了C++多线程学习(九、不安全的队列测试,简单封装线程安全队列)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

不安全的队列测试

简单封装一个线程安全队列


不安全的队列测试

下方是一个简单的程序,但是不安全:

由于代码中的线程t是在后台运行的,所以无法确定线程t是否已经完成了对myQ队列的操作,因此在主线程中处理myQ队列时,可能会出现竞争条件或者数据不一致的情况,导致输出的结果不确定。文章来源地址https://www.toymoban.com/news/detail-547556.html

#include<iostream>
#include<thread>
#include<queue>
using namespace std;
void InsertData(queue<int>& data, int num)
{
	data.push(num);
}
void test()
{
	queue<int> myQ;
	for (int i = 0; i < 10; i++)
	{
		thread t(InsertData,ref(myQ), ref(i));
		//t.join();用join是没毛病的
		t.detach();//但是驻留后台,就不一定会稳定,线程会不安全
	}
	this_thread::sleep_for(3s);
	while (!myQ.empty())
	{
		cout << myQ.front() << endl;
		myQ.pop();
	}
}

int main()
{
	test();

	return 0;
}

简单封装一个线程安全队列

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
template<class T>
class Thread_Safe_Queue
{
public:
	Thread_Safe_Queue() {};//构造函数
	Thread_Safe_Queue(Thread_Safe_Queue const& other) //拷贝函数
	{
		lock_guard<mutex> CopyLock(other.mut);//自动加锁
		DataQueue = other.DataQueue;
	};
	void PushData(T NewData)//入数据
	{
		lock_guard<mutex> CopyLock(mut);//自动加锁
		DataQueue.push(NewData);
		DataCond.notify_one();//数据存储完毕后,随机唤醒另一个准备完毕的线程
	}
	//等待数据插入结束后在执行数据的出队过程
	void WaitPop(T& OldData)
	{
		unique_lock<mutex> CopyLock(mut);//手动加锁
		DataCond.wait(CopyLock, [this] { return !DataQueue.empty() || DataReady; });//等到数据不为空或者有新数据到来的时候,再进行出队的过程
		if (!DataQueue.empty())
		{
			OldData = DataQueue.front();
			DataQueue.pop();
		}
		DataReady = false; // 重置标志
	}
	shared_ptr<T> WaitPop()//重载一下
	{
		unique_lock<mutex> CopyLock(mut);//手动加锁
		DataCond.wait(CopyLock, [this] { return !DataQueue.empty() || DataReady; });//等到数据不为空或者有新数据到来的时候,再进行出队的过程
		if (!DataQueue.empty())
		{
			shared_ptr<T> res(make_shared<T>(DataQueue.front()));
			DataQueue.pop();
			DataReady = false; // 重置标志
			return res;
		}
		return nullptr; // 返回nullptr表示没有数据可取
	}
	bool empty() const //判断是否为空
	{
		lock_guard<mutex> lk(mut);//加锁
		return DataQueue.empty();
	}
protected:
	mutable mutex mut;//互斥锁,用于保护队列DataQueue的访问
	queue<T> DataQueue;//数据队列
	condition_variable DataCond;//用于线程之间的同步,等待某个条件的发生
	bool DataReady = false; // 标记是否有新数据到来
};

//测试函数
void testInsert(Thread_Safe_Queue<int>& data, int num)
{
	data.PushData(num);
}

void ThreadSafeTest()
{
	Thread_Safe_Queue<int> myQ;
	for (int i = 0; i < 1500; i++)
	{
		thread t(testInsert, ref(myQ), ref(i));
		t.detach();
	}
	//this_thread::sleep_for(1s);
	int num = 0;
	while (true)
	{
		auto res = myQ.WaitPop();
		if (res == nullptr)
			break;
		cout << *res << "\n";
	}
}

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

到了这里,关于C++多线程学习(九、不安全的队列测试,简单封装线程安全队列)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++线程的简单学习及了解

    此篇文章只是线程的简单了解。 文章目录 前言 一、线程的优缺点 二、C++线程库 1.thread类的简单介绍 2.线程函数参数 总结 什么是线程? 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列” 一切进程至少都有一个执行线

    2023年04月27日
    浏览(52)
  • 【线程】封装 | 安全 | 互斥

    1.组件式的封装出一个线程类(像C++11线程库那样去管理线程) 我们并不想暴露出线程创建,终止,等待,分离,获取线程id等POSIX线程库的接口,我们也想像C++11那样通过面向对象的方式来玩,所以接下来我们将POSIX线程库的接口做一下封装,同样能实现像C++11线程库那样去管

    2024年03月22日
    浏览(40)
  • Qt QQueue 安全的多线程队列、阻塞队列

    在C++中,queue是一个模板类,用于实现队列数据结构,遵循先进先出的原则。 ♦ 常用方法: · ♦ 简单使用: · ♦ 打印: · QQueue 继承与 QList ♦ 常用方法: · ♦ 实例: · ♦ 打印: · 在多线程编程中,由于QQueue并不是线程安全的,因此我们需要先使用互斥锁(QMutex)来保

    2024年02月16日
    浏览(39)
  • 多线程环境下如何安全的使用线性表, 队列, 哈希表

    内心丰盈者, 独行也如众 使用synchronized锁或者reentrantLock锁 使用CopyOnWriteArrayList(COW写时拷贝)类来代替ArrayList类. 多个线程对CopyOnWriteArrayList里面的ArrayList进行读操作, 不会发生线程安全问题, 不做任何处理 多个线程对CopyOnWriteArrayList里面的ArrayList进行写操作, 会为每个线程创建一

    2024年02月07日
    浏览(57)
  • C++ 学习笔记、01 | 开发简单职工管理系统遇到的一些问题

    记录开发简单职工管理系统遇到的一些问题,黑马教程 https://www.bilibili.com/video/BV1et411b73Z P147 ~ P166 头文件只声明,源文件来实现(本质上是类内声明类外实现) 源文件需要引用特定的头文件 #ifndef 的方式依赖于宏名字不能冲突( 最好采用这种方式 ) 保证同一个文件只会被编

    2024年02月08日
    浏览(39)
  • 【Linux后端服务器开发】封装线程池实现TCP多线程通信

    目录 一、线程池模块 Thread.h LockGuard.h ThreadPool.h 二、任务模块模块 Task.h 三、日志模块 Log.h 四、守护进程模块 Deamon.h  五、TCP通信模块 Server.h Client.h server.cpp client.cpp 关于TCP通信协议的封装,此篇博客有详述: 【Linux后端服务器开发】TCP通信设计_命运on-9的博客-CSDN博客 线程池

    2024年02月16日
    浏览(45)
  • UE4/5C++多线程插件制作(十三、优化,bug,尝试打包【尚未完成插件封装,初次测试】)

    目录 MTPPlatform.h MTPMarco.h  MTPSemaphore.h  MTPSemaphore.cpp  RTPRunnable.cpp  模板问题 打包问题 /

    2024年02月15日
    浏览(46)
  • JavaEE 初阶篇-线程安全的集合类、多线程环境使用 ArrayList、队列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的区别)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍   文章目录         1.0 线程安全的集合类         1.2 线程安全的集合类 - Vector         1.3 线程安全的集合类 - Stack         1.4 线程安全的集合类 - HashTable         2.0 多线程环境使用 ArrayList        

    2024年04月25日
    浏览(51)
  • Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列

    JUC是java.util.concurrent包的简称,在Java5.0添加,目的就是为了更好的支持高并发任务。让开发者进行多线程编程时减少竞争条件和死锁的问题 java.lang.Thread.State tools(工具类):又叫信号量三组工具类,包含有 CountDownLatch(闭锁) 是一个同步辅助类,在完成一组正在其他线程中

    2024年02月05日
    浏览(35)
  • 让开发回归简单模式-组件封装

            对于工作年限不长的程序员来说,知识储备是非常关键的。在开发中各种技术的应用已经非常普遍了,例如常见的各种ORM,各种中间件如Redis,MQ等等,又如WebApi路由配置等等,对于常常做开发的程序员来说,都是小事,我们就从小事说起。         在微服务中,

    2024年02月09日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包