中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

梅州南站30條新聞?wù)?/h1>

梅州南站,30條新聞?wù)?如何在vps上搭建網(wǎng)站,在線(xiàn)傳媒有限公司目錄 一、thread類(lèi)的介紹二、線(xiàn)程函數(shù)參數(shù)三、 原子性操作庫(kù)四、lock_guard與unique_lock4.1、mutex的種類(lèi)4.2 lock_guard4.3 unique_lock 一、thread類(lèi)的介紹 在C11之前,涉及到多線(xiàn)程問(wèn)題,都是和平臺(tái)相關(guān)的,比如**windows和linux下各有自己…

目錄

  • 一、thread類(lèi)的介紹
  • 二、線(xiàn)程函數(shù)參數(shù)
  • 三、 原子性操作庫(kù)
  • 四、lock_guard與unique_lock
    • 4.1、mutex的種類(lèi)
    • 4.2 lock_guard
    • 4.3 unique_lock

一、thread類(lèi)的介紹

在C++11之前,涉及到多線(xiàn)程問(wèn)題,都是和平臺(tái)相關(guān)的,比如**windows和linux下各有自己的接口,這使得代碼的可移植性比較差。C++11中最重要的特性就是對(duì)線(xiàn)程進(jìn)行支持了,使得C++在并行編程時(shí)不需要依賴(lài)第三方庫(kù),**而且在原子操作中還引入了原子類(lèi)的概念。要使用標(biāo)準(zhǔn)庫(kù)中的線(xiàn)程,必須包含< thread >頭文件。

函數(shù)名功能
thread()構(gòu)造一個(gè)線(xiàn)程對(duì)象,沒(méi)有關(guān)聯(lián)任何線(xiàn)程函數(shù),即沒(méi)有啟動(dòng)任何線(xiàn)程
thread(fn, args1, args2,…)構(gòu)造一個(gè)線(xiàn)程對(duì)象,并關(guān)聯(lián)線(xiàn)程函數(shù)fn,args1,args2,…為線(xiàn)程函數(shù)的參數(shù)
get_id()獲取線(xiàn)程id
jionable()線(xiàn)程是否還在執(zhí)行,joinable代表的是一個(gè)正在執(zhí)行中的線(xiàn)程。
jion()該函數(shù)調(diào)用后會(huì)阻塞住線(xiàn)程,當(dāng)該線(xiàn)程結(jié)束后,主線(xiàn)程繼續(xù)執(zhí)行
detach()在創(chuàng)建線(xiàn)程對(duì)象后馬上調(diào)用,用于把被創(chuàng)建線(xiàn)程與線(xiàn)程對(duì)象分離開(kāi),分離的線(xiàn)程變?yōu)楹笈_(tái)線(xiàn)程,創(chuàng)建的線(xiàn)程的"死活"就與主線(xiàn)程無(wú)關(guān)

注意:

  1. 線(xiàn)程是操作系統(tǒng)中的一個(gè)概念,線(xiàn)程對(duì)象可以關(guān)聯(lián)一個(gè)線(xiàn)程,用來(lái)控制線(xiàn)程以及獲取線(xiàn)程的狀態(tài)。
  2. 當(dāng)創(chuàng)建一個(gè)線(xiàn)程對(duì)象后,沒(méi)有提供線(xiàn)程函數(shù),該對(duì)象實(shí)際沒(méi)有對(duì)應(yīng)任何線(xiàn)程。
#include <thread>
int main()
{std::thread t1;cout << t1.get_id() << endl;return 0;
}

get_id()的返回值類(lèi)型為id類(lèi)型,id類(lèi)型實(shí)際為std::thread命名空間下封裝的一個(gè)類(lèi),該類(lèi)中包含了一個(gè)結(jié)構(gòu)體:
在這里插入圖片描述

  1. 當(dāng)創(chuàng)建一個(gè)線(xiàn)程對(duì)象后,并且給線(xiàn)程關(guān)聯(lián)線(xiàn)程函數(shù),該線(xiàn)程就被啟動(dòng),與主線(xiàn)程一起運(yùn)行。線(xiàn)程函數(shù)一般情況下可按照以下三種方式提供:
    1.函數(shù)指針
    2.lambda表達(dá)式
    3.函數(shù)對(duì)象
#include <iostream>
using namespace std;
#include <thread>
void ThreadFunc(int a)
{cout << "Thread1" << a << endl;
}
class TF
{
public:void operator()(){cout << "Thread3" << endl;}
};
int main()
{// 線(xiàn)程函數(shù)為函數(shù)指針thread t1(ThreadFunc, 10);// 線(xiàn)程函數(shù)為lambda表達(dá)式thread t2([] {cout << "Thread2" << endl; });// 線(xiàn)程函數(shù)為函數(shù)對(duì)象TF tf;thread t3(tf);t1.join();t2.join();t3.join();cout << "Main thread!" << endl;return 0;
}
  1. thread類(lèi)是防拷貝的,不允許拷貝構(gòu)造以及賦值,但是可以移動(dòng)構(gòu)造和移動(dòng)賦值,即將一個(gè)線(xiàn)程對(duì)象關(guān)聯(lián)線(xiàn)程的狀態(tài)轉(zhuǎn)移給其他線(xiàn)程對(duì)象,轉(zhuǎn)移期間不意向線(xiàn)程的執(zhí)行。
  2. 可以通過(guò)jionable()函數(shù)判斷線(xiàn)程是否是有效的,如果是以下任意情況,則線(xiàn)程無(wú)效。
    1.采用無(wú)參構(gòu)造函數(shù)構(gòu)造的線(xiàn)程對(duì)象
    2.線(xiàn)程對(duì)象的狀態(tài)已經(jīng)轉(zhuǎn)移給其他線(xiàn)程對(duì)象
    3.線(xiàn)程已經(jīng)調(diào)用jion或者detach結(jié)束

二、線(xiàn)程函數(shù)參數(shù)

線(xiàn)程函數(shù)的參數(shù)是以值拷貝的方式拷貝到線(xiàn)程??臻g中的,因此:即使線(xiàn)程參數(shù)為引用類(lèi)型,在線(xiàn)程中修改后也不能修改外部實(shí)參,因?yàn)?strong>其實(shí)際引用的是線(xiàn)程棧中的拷貝,而不是外部實(shí)參。

void ThreadFunc1(int& x)
{x += 10;
}
void ThreadFunc2(int* x)
{*x += 10;
}
int main()
{int a = 10;// 在線(xiàn)程函數(shù)中對(duì)a修改,不會(huì)影響外部實(shí)參,因?yàn)?#xff1a;線(xiàn)程函數(shù)參數(shù)雖然是引用方式,但其實(shí)際引用的是線(xiàn)程棧中的拷貝/*thread t1(ThreadFunc1, a);t1.join();cout << a << endl;*/// 如果想要通過(guò)形參改變外部實(shí)參時(shí),必須借助std::ref()函數(shù)thread t2(ThreadFunc1, std::ref(a));t2.join();cout << a << endl; 地址的拷貝thread t3(ThreadFunc2, &a);t3.join();cout << a << endl;return 0;
}

運(yùn)行結(jié)果:
在這里插入圖片描述
注意:如果是類(lèi)成員函數(shù)作為線(xiàn)程參數(shù)時(shí),必須將this作為線(xiàn)程函數(shù)參數(shù)。

三、 原子性操作庫(kù)

多線(xiàn)程最主要的問(wèn)題是共享數(shù)據(jù)帶來(lái)的問(wèn)題(即線(xiàn)程安全)。如果共享數(shù)據(jù)都是只讀的,那么沒(méi)問(wèn)
題,因?yàn)橹蛔x操作不會(huì)影響到數(shù)據(jù),更不會(huì)涉及對(duì)數(shù)據(jù)的修改,所以所有線(xiàn)程都會(huì)獲得同樣的數(shù)
據(jù)。但是,當(dāng)一個(gè)或多個(gè)線(xiàn)程要修改共享數(shù)據(jù)時(shí),就會(huì)產(chǎn)生很多潛在的麻煩。比如:

#include <iostream>
#include <thread>
using namespace std;
unsigned long sum = 0;
void fun(size_t num)
{for (size_t i = 0; i < num; ++i)sum++;
}
int main()
{cout << "Before joining,sum = " << sum << std::endl;thread t1(fun, 10000000);thread t2(fun, 10000000);t1.join();t2.join();cout << "After joining,sum = " << sum << std::endl;return 0;
}

運(yùn)行結(jié)果:
在這里插入圖片描述
C++98中傳統(tǒng)的解決方式:可以對(duì)共享修改的數(shù)據(jù)可以加鎖保護(hù)。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;std::mutex m;
unsigned long sum = 0;
void fun(size_t num)
{for (size_t i = 0; i < num; ++i){m.lock();sum++;m.unlock();}
}
int main()
{cout << "Before joining,sum = " << sum << std::endl;thread t1(fun, 10000000);thread t2(fun, 10000000);t1.join();t2.join();cout << "After joining,sum = " << sum << std::endl;return 0;
}

運(yùn)行結(jié)果:
在這里插入圖片描述
雖然加鎖可以解決,但是加鎖有一個(gè)缺陷就是:只要一個(gè)線(xiàn)程在對(duì)sum++時(shí),其他線(xiàn)程就會(huì)被阻
塞,會(huì)影響程序運(yùn)行的效率,而且鎖如果控制不好,還容易造成死鎖。
因此C++11中引入了原子操作。所謂原子操作:即不可被中斷的一個(gè)或一系列操作,C++11引入
的原子操作類(lèi)型,使得線(xiàn)程間數(shù)據(jù)的同步變得非常高效。

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;atomic_long sum{ 0 };
void fun(size_t num)
{for (size_t i = 0; i < num; ++i)sum++; // 原子操作
}
int main()
{cout << "Before joining, sum = " << sum << std::endl;thread t1(fun, 1000000);thread t2(fun, 1000000);t1.join();t2.join();cout << "After joining, sum = " << sum << std::endl;return 0;
}

運(yùn)行結(jié)果:
在這里插入圖片描述
在C++11中,程序員不需要對(duì)原子類(lèi)型變量進(jìn)行加鎖解鎖操作,線(xiàn)程能夠?qū)υ宇?lèi)型變量互斥的
訪問(wèn)。更為普遍的,程序員可以使用atomic類(lèi)模板,定義出需要的任意原子類(lèi)型

atmoic t; // 聲明一個(gè)類(lèi)型為T(mén)的原子類(lèi)型變量t

注意:原子類(lèi)型通常屬于"資源型"數(shù)據(jù),多個(gè)線(xiàn)程只能訪問(wèn)單個(gè)原子類(lèi)型的拷貝,因此在C++11
中,原子類(lèi)型只能從其模板參數(shù)中進(jìn)行構(gòu)造,不允許原子類(lèi)型進(jìn)行拷貝構(gòu)造、移動(dòng)構(gòu)造以及
operator=等,為了防止意外,標(biāo)準(zhǔn)庫(kù)已經(jīng)將atmoic模板類(lèi)中的拷貝構(gòu)造、移動(dòng)構(gòu)造、賦值運(yùn)算
符重載默認(rèn)刪除掉了。

#include <atomic>
int main()
{atomic<int> a1(0);//atomic<int> a2(a1); // 編譯失敗atomic<int> a2(0);//a2 = a1; // 編譯失敗return 0;
}

以下是原子類(lèi)型名稱(chēng)與之對(duì)應(yīng)的內(nèi)置類(lèi)型名稱(chēng)
在這里插入圖片描述

四、lock_guard與unique_lock

在多線(xiàn)程環(huán)境下,如果想要保證某個(gè)變量的安全性,只要將其設(shè)置成對(duì)應(yīng)的原子類(lèi)型即可,即高
效又不容易出現(xiàn)死鎖問(wèn)題。但是有些情況下,我們可能需要保證一段代碼的安全性,那么就只能
通過(guò)鎖的方式來(lái)進(jìn)行控制。
比如:一個(gè)線(xiàn)程對(duì)變量number進(jìn)行加一100次,另外一個(gè)減一100次,每次操作加一或者減一之
后,輸出number的結(jié)果,要求:number最后的值為1。

#include <thread>
#include <mutex>
int number = 0;
mutex g_lock;
int ThreadProc1()
{for (int i = 0; i < 100; i++){g_lock.lock();++number;cout << "thread 1 :" << number << endl;g_lock.unlock();}return 0;
}
int ThreadProc2()
{for (int i = 0; i < 100; i++){g_lock.lock();--number;cout << "thread 2 :" << number << endl;g_lock.unlock();}return 0;
}
int main()
{thread t1(ThreadProc1);thread t2(ThreadProc2);t1.join();t2.join();cout << "number:" << number << endl;system("pause");return 0;
}

上述代碼的缺陷:鎖控制不好時(shí),可能會(huì)造成死鎖,最常見(jiàn)的比如在鎖中間代碼返回,或者在鎖
的范圍內(nèi)拋異常
。因此:C++11采用RAII的方式對(duì)鎖進(jìn)行了封裝,即lock_guard和unique_lock。

4.1、mutex的種類(lèi)

在C++11中,Mutex總共包了四個(gè)互斥量的種類(lèi):

1. std::mutex
C++11提供的最基本的互斥量,該類(lèi)的對(duì)象之間不能拷貝,也不能進(jìn)行移動(dòng)。mutex最常用
的三個(gè)函數(shù):

函數(shù)名函數(shù)功能
lock()上鎖:鎖住互斥量
unlock()解鎖:釋放對(duì)互斥量的所有權(quán)
try_lock()嘗試鎖住互斥量,如果互斥量被其他線(xiàn)程占有,則當(dāng)前線(xiàn)程也不會(huì)被阻塞

注意,線(xiàn)程函數(shù)調(diào)用lock()時(shí),可能會(huì)發(fā)生以下三種情況:

  • 如果該互斥量當(dāng)前沒(méi)有被鎖住,則調(diào)用線(xiàn)程將該互斥量鎖住,直到調(diào)用 unlock之前,
  • 該線(xiàn)程一直擁有該鎖
  • 如果當(dāng)前互斥量被其他線(xiàn)程鎖住,則當(dāng)前的調(diào)用線(xiàn)程被阻塞住
  • 如果當(dāng)前互斥量被當(dāng)前調(diào)用線(xiàn)程鎖住,則會(huì)產(chǎn)生死鎖(deadlock)

線(xiàn)程函數(shù)調(diào)用try_lock()時(shí),可能會(huì)發(fā)生以下三種情況:

  • 如果當(dāng)前互斥量沒(méi)有被其他線(xiàn)程占有,則該線(xiàn)程鎖住互斥量,直到該線(xiàn)程調(diào)用 unlock釋放互斥量
  • 如果當(dāng)前互斥量被其他線(xiàn)程鎖住,則當(dāng)前調(diào)用線(xiàn)程返回 false,而并不會(huì)被阻塞掉
  • 如果當(dāng)前互斥量被當(dāng)前調(diào)用線(xiàn)程鎖住,則會(huì)產(chǎn)生死鎖(deadlock)

2. std::recursive_mutex
其允許同一個(gè)線(xiàn)程對(duì)互斥量多次上鎖(即遞歸上鎖),來(lái)獲得對(duì)互斥量對(duì)象的多層所有權(quán),釋放互斥量時(shí)需要調(diào)用與該鎖層次深度相同次數(shù)的 unlock(),除此之外,std::recursive_mutex 的特性和 std::mutex 大致相同。

3. std::timed_mutex
比 std::mutex 多了兩個(gè)成員函數(shù),try_lock_for(),try_lock_until() 。

  • try_lock_for()
    接受一個(gè)時(shí)間范圍,表示在這一段時(shí)間范圍之內(nèi)線(xiàn)程如果沒(méi)有獲得鎖則被阻塞住(與std::mutex 的 try_lock() 不同,try_lock 如果被調(diào)用時(shí)沒(méi)有獲得鎖則直接返回false),如果在此期間其他線(xiàn)程釋放了鎖,則該線(xiàn)程可以獲得對(duì)互斥量的鎖,如果超時(shí)(即在指定時(shí)間內(nèi)還是沒(méi)有獲得鎖),則返回 false。
  • try_lock_until()
    接受一個(gè)時(shí)間點(diǎn)作為參數(shù),在指定時(shí)間點(diǎn)未到來(lái)之前線(xiàn)程如果沒(méi)有獲得鎖則被阻塞住,如果在此期間其他線(xiàn)程釋放了鎖,則該線(xiàn)程可以獲得對(duì)互斥量的鎖,如果超時(shí)(即在指定時(shí)間內(nèi)還是沒(méi)有獲得鎖),則返回 false。

4. std::recursive_timed_mutex

4.2 lock_guard

std::lock_gurad 是 C++11 中定義的模板類(lèi)。定義如下:

template<class _Mutex>
class lock_guard
{
public:// 在構(gòu)造lock_gard時(shí),_Mtx還沒(méi)有被上鎖explicit lock_guard(_Mutex& _Mtx): _MyMutex(_Mtx){_MyMutex.lock();}// 在構(gòu)造lock_gard時(shí),_Mtx已經(jīng)被上鎖,此處不需要再上鎖lock_guard(_Mutex& _Mtx, adopt_lock_t): _MyMutex(_Mtx){}~lock_guard() _NOEXCEPT{_MyMutex.unlock();}lock_guard(const lock_guard&) = delete;lock_guard& operator=(const lock_guard&) = delete;
private:_Mutex& _MyMutex;
};

通過(guò)上述代碼可以看到,lock_guard類(lèi)模板主要是通過(guò)RAII的方式,對(duì)其管理的互斥量進(jìn)行了封裝,在需要加鎖的地方,只需要用上述介紹的任意互斥體實(shí)例化一個(gè)lock_guard,調(diào)用構(gòu)造函數(shù)成功上鎖,出作用域前,lock_guard對(duì)象要被銷(xiāo)毀,調(diào)用析構(gòu)函數(shù)自動(dòng)解鎖,可以有效避免死鎖問(wèn)題。
lock_guard的缺陷:太單一,用戶(hù)沒(méi)有辦法對(duì)該鎖進(jìn)行控制,因此C++11又提供了unique_lock。

4.3 unique_lock

與lock_gard類(lèi)似,unique_lock類(lèi)模板也是采用RAII的方式對(duì)鎖進(jìn)行了封裝,并且也是以獨(dú)占所有權(quán)的方式管理mutex對(duì)象的上鎖和解鎖操作,即其對(duì)象之間不能發(fā)生拷貝。在構(gòu)造(或移動(dòng)(move)賦值)時(shí),unique_lock 對(duì)象需要傳遞一個(gè) Mutex 對(duì)象作為它的參數(shù),新創(chuàng)建的unique_lock 對(duì)象負(fù)責(zé)傳入的 Mutex 對(duì)象的上鎖和解鎖操作。使用以上類(lèi)型互斥量實(shí)例化unique_lock的對(duì)象時(shí),自動(dòng)調(diào)用構(gòu)造函數(shù)上鎖,unique_lock對(duì)象銷(xiāo)毀時(shí)自動(dòng)調(diào)用析構(gòu)函數(shù)解鎖,可以很方便的防止死鎖問(wèn)題。
與lock_guard不同的是,unique_lock更加的靈活,提供了更多的成員函數(shù):

  • 上鎖/解鎖操作:lock、try_lock、try_lock_for、try_lock_until和unlock
  • 修改操作:移動(dòng)賦值、交換(swap:與另一個(gè)unique_lock對(duì)象互換所管理的互斥量所有權(quán))、釋放(release:返回它所管理的互斥量對(duì)象的指針,并釋放所有權(quán))
  • 獲取屬性:owns_lock(返回當(dāng)前對(duì)象是否上了鎖)、operator bool()(與owns_lock()的功能相同)、mutex(返回當(dāng)前unique_lock所管理的互斥量的指針)
http://www.risenshineclean.com/news/55119.html

相關(guān)文章:

  • 如何用div和css做購(gòu)物網(wǎng)站關(guān)鍵詞歌詞打印
  • wordpress 3.4.2多地優(yōu)化完善疫情防控措施
  • 網(wǎng)站怎么維護(hù)更新bing搜索引擎入口
  • 學(xué)校門(mén)戶(hù)網(wǎng)站什么意思外貿(mào)網(wǎng)站大全
  • 深圳最近消息自己做seo網(wǎng)站推廣
  • 網(wǎng)站開(kāi)發(fā)要服務(wù)器嗎東莞網(wǎng)站推廣企業(yè)
  • 有哪些網(wǎng)站可以做外貿(mào)網(wǎng)站推廣的途徑和方法
  • h5 做的網(wǎng)站 價(jià)格葫島百度seo
  • 做gif動(dòng)圖的網(wǎng)站犯法嗎seo文章優(yōu)化技巧
  • 個(gè)人可以做視頻網(wǎng)站嗎企業(yè)查詢(xún)寶
  • 大慶開(kāi)發(fā)網(wǎng)站公司每日新聞
  • 怎么注冊(cè)網(wǎng)站賬號(hào)seo查詢(xún)
  • 哈爾濱網(wǎng)站建設(shè)信息網(wǎng)站如何做優(yōu)化排名
  • 現(xiàn)成的手機(jī)網(wǎng)站做APP最近實(shí)時(shí)熱點(diǎn)事件
  • 培訓(xùn)網(wǎng)站建設(shè)永州網(wǎng)站seo
  • 網(wǎng)站建設(shè)入門(mén)教程對(duì)網(wǎng)絡(luò)營(yíng)銷(xiāo)的認(rèn)識(shí)800字
  • 網(wǎng)頁(yè)工具東莞優(yōu)化排名公司
  • 農(nóng)業(yè)網(wǎng)站建設(shè)方案 ppt搜索推廣平臺(tái)
  • 有什么網(wǎng)站是做平面設(shè)計(jì)的百度搜索的優(yōu)勢(shì)
  • 真人性做爰video網(wǎng)站公司網(wǎng)站建站要多少錢(qián)
  • 深圳做積分商城網(wǎng)站建設(shè)怎么制作鏈接網(wǎng)頁(yè)
  • 深圳分銷(xiāo)網(wǎng)站設(shè)計(jì)電話(huà)企業(yè)網(wǎng)站建設(shè)
  • 公司建一個(gè)網(wǎng)站嗎搜什么關(guān)鍵詞能搜到好片
  • 廣州知名網(wǎng)站建設(shè)哪家公司好seo文案范例
  • 產(chǎn)品網(wǎng)站建設(shè)軟文推廣營(yíng)銷(xiāo)平臺(tái)
  • 家里電腦做網(wǎng)站服務(wù)器seo推廣怎么樣
  • 網(wǎng)站開(kāi)發(fā)什么意思徐州seo公司
  • 河南新鄉(xiāng)市建設(shè)銀行網(wǎng)站系統(tǒng)優(yōu)化軟件排行榜
  • 競(jìng)價(jià)網(wǎng)站做seo教育培訓(xùn)機(jī)構(gòu)官網(wǎng)
  • 武漢網(wǎng)絡(luò)推廣有哪些公司鄂爾多斯seo