iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++详解如何实现两个线程交替打印
  • 147
分享到

C++详解如何实现两个线程交替打印

2024-04-02 19:04:59 147人浏览 八月长安
摘要

c++线程库,点击此处查看文档 首先简单搭一个框架,让两个线程先尝试实现交替打印。 //实现两个线程交替打印 #include <iOStream> #include &

c++线程库,点击此处查看文档

首先简单搭一个框架,让两个线程先尝试实现交替打印。

//实现两个线程交替打印
#include <iOStream>
#include <thread>
using namespace std;
int main(void)
{
	int n = 100;
	int i = 0;
	//创建两个线程
	thread t1([&n, &i](){
		while (i < n)
		{
			cout << i << " ";
			i++;
		}
	});
	thread t2([&n, &i]() {
		while (i < n)
		{
			cout << i << " ";
			i++;
		}
	});
	if (t1.joinable())
	{
		t1.join();
	}
	if (t2.joinable())
	{
		t2.join();
	}
	return 0;
}

为了让我们更加清楚是哪个线程打印了,我们需要获取线程的ID。

#include <iostream>
#include <thread>
using namespace std;
int main(void)
{
	int n = 100;
	int i = 0;
	//创建两个线程
	thread t1([&n, &i](){
		while (i < n)
		{
			cout << this_thread::get_id()  << ": " << i << endl;
			i++;
		}
	});
	thread t2([&n, &i]() {
		while (i < n)
		{
			cout << this_thread::get_id() << ": " << i << endl;
			i++;
		}
	});
	if (t1.joinable())
	{
		t1.join();
	}
	if (t2.joinable())
	{
		t2.join();
	}
	return 0;
}

这显然没有完成两个线程交替打印的目的,甚至数据的打印都非常地乱。这是因为i是临界资源,多个线程争抢访问临界资源可能会造成数据二义,线程是不安全的,需要保证任意时刻只有一个线程能够访问临界资源。

所以创建一个互斥量,并在临界区合适的地方加和解锁。由于线程的执行函数我使用了lambda表达式,为了让两个线程使用的是同一把锁,把锁创建在了main函数内,并在lambda表达式内使用了引用捕捉。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	//创建两个线程
	thread t1([&n, &i, &mtx](){
		while (i < n)
		{
			mtx.lock();
			cout << this_thread::get_id()  << ": " << i << endl;
			i++;
			mtx.unlock();
		}
	});
	thread t2([&n, &i, &mtx]() {
		while (i < n)
		{
			mtx.lock();
			cout << this_thread::get_id() << ": " << i << endl;
			i++;
			mtx.unlock();
		}
	});
	if (t1.joinable())
	{
		t1.join();
	}
	if (t2.joinable())
	{
		t2.join();
	}
	return 0;
}

在C++中,一般不直接操作锁,而是由类去管理锁。

//第一个管理锁的类
template <class Mutex> class lock_guard;
//第二个管理锁的类
template <class Mutex> class unique_lock;

lock_guar类,只有构造和析构函数。一般用于加锁和解锁,这里进行简单的模拟:

//注意:为了使得加锁和解锁的是同一把锁
//需要使用引用
template <class Lock>
class LockGuard
{
public:
	LockGuard(Lock &lck)
		:_lock(lck)
	{
		_lock.lock();
	}
	~LockGuard()
	{
		_lock.unlock();
	}
private:
	Lock &_lock;
};

unique_lock的成员方法就不仅仅是析构函数和构造函数。详见文档unique_lock介绍和使用。

这里将锁交给unique_lock类的对象进行管理。

int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	//创建两个线程
	thread t1([&n, &i, &mtx, &cv, &flag](){
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			cout << this_thread::get_id()  << ": " << i << endl;
			i++;
		}
	});
	thread t2([&n, &i, &mtx, &cv, &flag]() {
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			cout << this_thread::get_id() << ": " << i << endl;
			i++;
		}
	});
	if (t1.joinable())
	{
		t1.join();
	}
	if (t2.joinable())
	{
		t2.join();
	}
	return 0;
}

线程是安全了,但如果其中一个线程竞争锁的能力比较强,那么可能会出现上面这种情况。

需要控制:一个线程执行一次后,如果再次去执行就不准许了,同时可以唤醒另一个进程去执行,如此循环往复达到交替打印的目的。所以可以增加一个条件变量,让某个线程在该条件变量下的阻塞队列等待。

C++库中线程在条件变量下的等待函数第一个参数注意是管理锁的类对象

int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	condition_variable cv;
	bool flag = false;
	//创建两个线程
	thread t1([&n, &i, &mtx, &cv, &flag](){
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			//!flag为真,那么获取后不会阻塞,优先运行
			cv.wait(LockManage, [&flag]() {return !flag; });
			cout << this_thread::get_id()  << ": " << i << endl;
			i++;
		}
	});
	thread t2([&n, &i, &mtx, &cv, &flag]() {
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			//flag为假,竞争到锁后,由于条件不满足,阻塞
			cv.wait(LockManage, [&flag]() {return flag; });
			cout << this_thread::get_id() << ": " << i << endl;
			i++;
		}
	});
	if (t1.joinable())
	{
		t1.join();
	}
	if (t2.joinable())
	{
		t2.join();
	}
	return 0;
}

这里flag以及lambda表达式的增加是非常巧妙的。flag的初始化值为false,让线程t2在[&flag]() {return false; }下等待,那么t2线程就会先执行。

线程t1竞争到了锁,但是由于不满足条件,会继续等待,所以就出现了上面的情况。

需要一个线程唤醒另一个线程之前,将flag的值进行修改。

int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	condition_variable cv;
	bool flag = false;
	//创建两个线程
	thread t1([&n, &i, &mtx, &cv, &flag](){
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			//!flag为真,那么获取后不会阻塞,优先运行
			cv.wait(LockManage, [&flag]() {return !flag; });
			cout << this_thread::get_id()  << ": " << i << endl;
			i++;
			flag = true;
			cv.notify_one();
		}
	});
	thread t2([&n, &i, &mtx, &cv, &flag]() {
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			//flag为假,竞争到锁后,由于条件不满足,阻塞
			cv.wait(LockManage, [&flag]() {return flag; });
			cout << this_thread::get_id() << ": " << i << endl;
			i++;
			flag = false;
			cv.notify_one();
		}
	});
	if (t1.joinable())
	{
		t1.join();
	}
	if (t2.joinable())
	{
		t2.join();
	}
	return 0;
}

最终,实现了两个线程交替打印(一个线程打印奇数、一个线程打印偶数)

到此这篇关于C++详解如何实现两个线程交替打印的文章就介绍到这了,更多相关C++线程交替打印内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++详解如何实现两个线程交替打印

本文链接: https://www.lsjlt.com/news/166080.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++详解如何实现两个线程交替打印
    C++线程库,点击此处查看文档 首先简单搭一个框架,让两个线程先尝试实现交替打印。 //实现两个线程交替打印 #include <iostream> #include &...
    99+
    2024-04-02
  • java怎么实现两个线程交替打印
    可以使用synchronized关键字和wait()、notify()方法来实现两个线程交替打印。 下面是一个简单的例子,其中A线程...
    99+
    2023-10-26
    java
  • go语言如何实现两个协程交替打印
    这篇“go语言如何实现两个协程交替打印”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“go语言如何实现两个协程交替打印”文章吧...
    99+
    2023-06-29
  • go语言实现两个协程交替打印
    目录方法一:使用两个channel方法二:使用一个channel方法一:使用两个channel 这里channel CA 必须要有缓冲区,否则最后会报错 fatal error: a...
    99+
    2024-04-02
  • Java 用两个线程交替打印数字和字母
    目录1. park 和 unpark2. synchronized、notify、wait3. Condition前一段时间听马士兵老师讲课,讲到某公司的一个面试,两个线程,其中一个...
    99+
    2024-04-02
  • Java中如何实现两个线程交替运行
    小编给大家分享一下Java中如何实现两个线程交替运行,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!收到老师的一个题目,让我准备两个流程,依次实现输出以下信息如:线...
    99+
    2023-06-21
  • Java中实现两个线程交替运行的方法
    今天笔者收到老师的一个题目,让我准备两个流程,依次实现输出以下信息 如: 线程A 打印 字母a ,线程B 打印数字1 线程A 打印 字母b ,线程B 打印数字2 线程A 打印 字母c...
    99+
    2024-04-02
  • Java实现线程按序交替执行的方法详解
    目录一、题目描述二、解题思路三、代码详解一、题目描述 题目:有a、b、c三个线程,使得它们按照abc依次执行10次。 二、解题思路 控制执行线程变量flag,利用lock锁来保证线程...
    99+
    2024-04-02
  • Java如何实现多线程循环打印
    这篇文章将为大家详细讲解有关Java如何实现多线程循环打印,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。wait-notify循环打印问题可以通过设置目标值,每个线程想打印目标值,如果拿到锁后这次轮到的数...
    99+
    2023-06-22
  • 如何实现两个文本同行交替输出的批处理
    这篇文章给大家分享的是有关如何实现两个文本同行交替输出的批处理的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。有两个文本如下(实际中并不知道两文本各有多少行):文本1.txtaaaaaaaaaaaaaaaaaaaa...
    99+
    2023-06-08
  • 如何浅析C#打印和C#打印预览的实现
    如何浅析C#打印和C#打印预览的实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。我们谈到C#打印和C#打印预览的实现其中主要就是包括:页面设置、打印预览、打印...
    99+
    2023-06-17
  • 前端实现打印功能的两种方法详解
    目录前言方法一:window.print()   方法二:利用iframe,iframe.contentWindow.print()补充:导出步骤总结:前言 前端...
    99+
    2023-01-06
    前端实现打印功能 前端打印语句 前端打印功能实现
  • php如何实现两个变量交换
    这篇文章主要介绍了php如何实现两个变量交换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。两个变量交换//方式一:比较清晰,有变量产生 $t...
    99+
    2024-04-02
  • c# 如何实现web打印插件
    目录客户端程序(Winform)1、监听Web端的WebSocket消息,这里有用到三方包:Fleck,开箱即用,非常方便。2、处理Html,将Html转换为图片:3、打印图片其他的...
    99+
    2024-04-02
  • c语言如何实现两个值互相交换的函数
    小编给大家分享一下c语言如何实现两个值互相交换的函数,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!c语言中实现两个值互换的函数。#include <...
    99+
    2023-06-15
  • C++如何实现二维图形的打印
    这篇文章主要介绍了C++如何实现二维图形的打印,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、下三角图形的打印#include<iostream>using&n...
    99+
    2023-06-29
  • C语言进程程序替换的实现详解
    目录进程程序替换替换原理替换函数替换函数名称助记进程程序替换 替换原理 使用fork创建子进程后执行的是和父进程相同的程序,但是那样并没有多大的意义,子进程往往会“程序替...
    99+
    2024-04-02
  • C++实现算法两个数字相加详解
    Add Two Numbers 两个数字相加 You have two numbers represented by a linked list, where each n...
    99+
    2024-04-02
  • Mysql如何同时交换两个表的表名详解
    Mysql同时交换两个表的表名 表重命名有两种方式,所以交换两表名也有两种方式: 1 . lock tables t1 write ,t2 write; alter table t1...
    99+
    2024-04-02
  • Golang如何实现两个正则表达式相交
    在Golang中,可以使用`regexp`包来实现正则表达式的相交操作。具体步骤如下:1. 导入`regexp`包:```goimp...
    99+
    2023-08-19
    Golang
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作