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;}

C++怎么实现两个线程交替打印

这显然没有完成两个线程交替打印的目的,甚至数据的打印都非常地乱。这是因为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++怎么实现两个线程交替打印

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

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

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线程就会先执行。

C++怎么实现两个线程交替打印

线程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++怎么实现两个线程交替打印,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/20984

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云亿速云认证作者
上一篇 2022年8月27日 下午5:00
下一篇 2022年8月27日 下午5:01

相关推荐

  • Google网页快照对抗小技巧是什么

    Google搜索引擎是大家经常用的搜索工具,更新内容快速,搜索内容准确,但是就是因为更新内容快速,导致有的时候特别讨厌,比如我删除了一个贴子,但是由于网站权值很高,你一发送这个贴子,Google就收录了,导致后来即使你删除了贴子也没有什么用&hellip;&hellip; 那么我们有…

    2022年9月26日
    26000
  • word字体放大后上半部分缺失怎么解决

    解决方法 1、首先我们把缺失的文字框选出来。 2、鼠标右键点击之后选择段落。 3、然后选择行距,这里点击单倍行距。然后点击确定。 4、这样就能看见字体恢复了正常。 读到这里,这篇“word字体放大后上半部分缺失怎么解决”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,…

    2022年9月11日
    29400
  • html中阴影样式怎么设置

    样式代码:1、文本阴影样式“text-shadow: h-shadow v-shadow blur color;”;2、边框阴影样式“box-shadow: h-shadow v-shadow blur spread color inset;”;3、图片阴影样式“filter:drop-shadow…

    2022年9月24日
    30800
  • windows KB4525237安装失败怎么解决

    根据情况不同,小编为大家准备了四种解决方案 名列前茅种方案: 重新下载安装补丁 在我们下载补丁的过程中可能就会遇到文件损坏的情况,所以破损的补丁安装包是无法安装成功的。 这种情况下可以尝试重新下载一个补丁安装包重新安装。 第二种方案: 更新升级最新的.net framework(目前是4.8版本) …

    2022年9月1日
    18300
  • windows xbox商店常见问题怎么解决

    xbox商店常见问题解决方法: 1、Xbox商店其实就是微软win10商店(Microsoft Store)。 2、我们可以直接在菜单中打开Microsoft Store,进行游戏的查看等。 3、我们也可以直接在搜索栏中搜索Xbox,然后打开“Xbox 控制台小帮手” 4、我们能够在侧栏目中点击“商…

    2022年9月22日
    28500
  • 如何查询mysql中所有表

    查询mysql数据库中所有表的方法:1、执行“mysql -u root -p”命令并输入密码来登录mysql数据库服务器;2、执行“USE 数据库名;”命令来切换到指定数据库;3、执行“show tables;”或“SHOW FULL TABLES;”命令,会以表格形式列出mysql数据库中的所有…

    2022年9月22日
    2.4K00
  • 怎么使用CSS混合模式让文字智能适配背景颜色

    页面上有一段文本,能否实现这段文本在不同背景色下展示不同的颜色?也就是俗称的智能变色。像是下面这样: 文本在黑色底色上表现为白色,在白色底色上表现为黑色。看似很复杂的一个效果,但是其实在 CSS 中非常好实现,今天就介绍这样一个小技巧,在 CSS 中,利用混合模式 mix-blend-mode: d…

    2022年9月8日
    23500
  • windows todesk如何传输文件

    todesk传输文件的方法 1、 打开ToDesk,进入“设备列表”,选中想要传输的对象 2、选中后,点击右侧的“文件传输”,就能将需要的文件传给对方了 3、或者还有一种方法,就是点击工具栏箭头按钮 4、选择“文件” 5、最后在其中选中文件夹就可以进行文件的传输了。 感谢各位的阅读,以上就是“win…

    2022年9月26日
    1.3K00
  • 如何进行CaptureFramework框架分析

    一、背景 应用服务监控是智能运维系统的重要组成部分。在UAV系统中,中间件增强框架(MOF)探针提供了应用画像及性能数据收集等功能,其中数据收集功能主要采集四类数据:实时数据、画像数据、调用链接数据生成以及线程数据分析数据。为实现实时数据采集,UAVStack设计了CaptureFramework框…

    2022年9月5日
    16200
  • video接口指的是什么

    video接口指的是“复合视频接口”,是音频、视频分离的视频接口,一般由三个独立RCA插头组成,其中V接口连接混合视频信号,为黄色插口;L接口连接左声道声音信号,为白色插口;R接口连接右声道声音信号,为红色插口。 本教程操作环境:windows7系统、Dell G3电脑。 video是什么接口 复合…

    2022年9月2日
    35700
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部