亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++詳解如何實現(xiàn)兩個線程交替打印

 更新時間:2022年08月26日 10:08:01   作者:小小酥誒  
這篇文章主要介紹了使用C++庫實現(xiàn)兩個線程交替打印,一個線程打印奇數(shù)、一個線程打印偶數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

C++線程庫,點擊此處查看文檔

首先簡單搭一個框架,讓兩個線程先嘗試實現(xiàn)交替打印。

//實現(xiàn)兩個線程交替打印
#include <iostream>
#include <thread>
using namespace std;
int main(void)
{
	int n = 100;
	int i = 0;
	//創(chuàng)建兩個線程
	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;
	//創(chuàng)建兩個線程
	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;
}

這顯然沒有完成兩個線程交替打印的目的,甚至數(shù)據(jù)的打印都非常地亂。這是因為i是臨界資源,多個線程爭搶訪問臨界資源可能會造成數(shù)據(jù)二義,線程是不安全的,需要保證任意時刻只有一個線程能夠訪問臨界資源。

所以創(chuàng)建一個互斥量,并在臨界區(qū)合適的地方加鎖和解鎖。由于線程的執(zhí)行函數(shù)我使用了lambda表達式,為了讓兩個線程使用的是同一把鎖,把鎖創(chuàng)建在了main函數(shù)內(nèi),并在lambda表達式內(nèi)使用了引用捕捉。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	//創(chuàng)建兩個線程
	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類,只有構(gòu)造和析構(gòu)函數(shù)。一般用于加鎖和解鎖,這里進行簡單的模擬:

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

unique_lock的成員方法就不僅僅是析構(gòu)函數(shù)和構(gòu)造函數(shù)。詳見文檔unique_lock介紹和使用。

這里將鎖交給unique_lock類的對象進行管理。

int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	//創(chuàng)建兩個線程
	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;
}

線程是安全了,但如果其中一個線程競爭鎖的能力比較強,那么可能會出現(xiàn)上面這種情況。

需要控制:一個線程執(zhí)行一次后,如果再次去執(zhí)行就不準許了,同時可以喚醒另一個進程去執(zhí)行,如此循環(huán)往復達到交替打印的目的。所以可以增加一個條件變量,讓某個線程在該條件變量下的阻塞隊列等待。

C++庫中線程在條件變量下的等待函數(shù)第一個參數(shù)注意是管理鎖的類對象

int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	condition_variable cv;
	bool flag = false;
	//創(chuàng)建兩個線程
	thread t1([&n, &i, &mtx, &cv, &flag](){
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			//!flag為真,那么獲取后不會阻塞,優(yōu)先運行
			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以及l(fā)ambda表達式的增加是非常巧妙的。flag的初始化值為false,讓線程t2在[&flag]() {return false; }下等待,那么t2線程就會先執(zhí)行。

線程t1競爭到了鎖,但是由于不滿足條件,會繼續(xù)等待,所以就出現(xiàn)了上面的情況。

需要一個線程喚醒另一個線程之前,將flag的值進行修改。

int main(void)
{
	int n = 100;
	int i = 0;
	mutex mtx;
	condition_variable cv;
	bool flag = false;
	//創(chuàng)建兩個線程
	thread t1([&n, &i, &mtx, &cv, &flag](){
		while (i < n)
		{
			unique_lock<mutex> LockManage(mtx);
			//!flag為真,那么獲取后不會阻塞,優(yōu)先運行
			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;
}

最終,實現(xiàn)了兩個線程交替打?。ㄒ粋€線程打印奇數(shù)、一個線程打印偶數(shù))

到此這篇關(guān)于C++詳解如何實現(xiàn)兩個線程交替打印的文章就介紹到這了,更多相關(guān)C++線程交替打印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言簡明清晰講解枚舉

    C語言簡明清晰講解枚舉

    枚舉法的本質(zhì)就是從所有候選答案中去搜索正確的解,枚舉算法簡單粗暴,他暴力的枚舉所有可能,盡可能地嘗試所有的方法,感興趣的朋友來看看吧
    2022-05-05
  • C++類型兼容規(guī)則詳情

    C++類型兼容規(guī)則詳情

    這篇文章主要介紹了C++類型兼容規(guī)則詳情,共有繼承時,任何需要父類對象的地方,都能使用子類對象“替代”,這就是類型兼容規(guī)則,下面一起來了解文章相關(guān)內(nèi)容吧
    2022-03-03
  • C++運算符重載與多繼承及二義性詳解

    C++運算符重載與多繼承及二義性詳解

    繼友元知識過后,就到了今天的C++運算符重載的內(nèi)容了,運算符重載是C++里比較重要的內(nèi)容。這篇博文不會一下子講完各種運算符重載,因為太多了了也不好吸收掌握,所以運算符重載我準備分多次記錄和分享,那么接下來進入正文
    2022-11-11
  • 求數(shù)組中最長遞增子序列的解決方法

    求數(shù)組中最長遞增子序列的解決方法

    本篇文章是對c++中求數(shù)組中最長遞增子序列的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法

    VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法

    本文主要介紹了VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • 深入理解C語言的邏輯控制

    深入理解C語言的邏輯控制

    這篇文章主要介紹了C語言的邏輯控制,對C語言的邏輯控制有較為深入的剖析,需要的朋友可以參考下
    2014-07-07
  • Visual?Studio?2022下載安裝與使用超詳細教程

    Visual?Studio?2022下載安裝與使用超詳細教程

    這篇文章主要介紹了Visual?Studio?2022最新版安裝與使用教程,本文以社區(qū)版為例通過圖文并茂的形式給大家介紹Visual?Studio?2022安裝使用,需要的朋友可以參考下
    2022-04-04
  • C語言 常量詳解及示例代碼

    C語言 常量詳解及示例代碼

    本文主要講解C語言 常量,這里整理了 C語言常量的基礎(chǔ)知識,并附代碼示例和示例詳細講解,希望能幫助開始學習C 語言的同學
    2016-08-08
  • C語言printf詳細解析

    C語言printf詳細解析

    C中格式字符串printf()的一般形式為: %[標志][輸出最小寬度][.精度][長度]類型, 其中方括號[]中的項為可選項。各項的意義介紹如下
    2013-09-09
  • C語言 while for do while循環(huán)體詳解用法

    C語言 while for do while循環(huán)體詳解用法

    在不少實際問題中有許多具有規(guī)律性的重復操作,因此在程序中就需要重復執(zhí)行某些語句。一組被重復執(zhí)行的語句稱之為循環(huán)體,能否繼續(xù)重復,決定循環(huán)的終止條件
    2021-10-10

最新評論