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)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云的头像亿速云
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

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

分享本页
返回顶部