在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ C/ 1.2 為什么使用并發(fā)?
3.4 本章總結(jié)
6.3 基于鎖設(shè)計(jì)更加復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
6.1 為并發(fā)設(shè)計(jì)的意義何在?
5.2 <code>C++</code>中的原子操作和原子類型
A.7 自動(dòng)推導(dǎo)變量類型
2.1 線程管理的基礎(chǔ)
8.5 在實(shí)踐中設(shè)計(jì)并發(fā)代碼
2.4 運(yùn)行時(shí)決定線程數(shù)量
2.2 向線程函數(shù)傳遞參數(shù)
第4章 同步并發(fā)操作
2.3 轉(zhuǎn)移線程所有權(quán)
8.3 為多線程性能設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)
6.4 本章總結(jié)
7.3 對(duì)于設(shè)計(jì)無(wú)鎖數(shù)據(jù)結(jié)構(gòu)的指導(dǎo)建議
關(guān)于這本書
A.1 右值引用
2.6 本章總結(jié)
D.2 &lt;condition_variable&gt;頭文件
A.6 變參模板
6.2 基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu)
4.5 本章總結(jié)
A.9 本章總結(jié)
前言
第10章 多線程程序的測(cè)試和調(diào)試
5.4 本章總結(jié)
第9章 高級(jí)線程管理
5.1 內(nèi)存模型基礎(chǔ)
2.5 識(shí)別線程
第1章 你好,C++的并發(fā)世界!
1.2 為什么使用并發(fā)?
A.5 Lambda函數(shù)
第2章 線程管理
4.3 限定等待時(shí)間
D.3 &lt;atomic&gt;頭文件
10.2 定位并發(fā)錯(cuò)誤的技術(shù)
附錄B 并發(fā)庫(kù)的簡(jiǎn)單比較
5.3 同步操作和強(qiáng)制排序
A.8 線程本地變量
第8章 并發(fā)代碼設(shè)計(jì)
3.3 保護(hù)共享數(shù)據(jù)的替代設(shè)施
附錄D C++線程庫(kù)參考
第7章 無(wú)鎖并發(fā)數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
D.7 &lt;thread&gt;頭文件
D.1 &lt;chrono&gt;頭文件
4.1 等待一個(gè)事件或其他條件
A.3 默認(rèn)函數(shù)
附錄A 對(duì)<code>C++</code>11語(yǔ)言特性的簡(jiǎn)要介紹
第6章 基于鎖的并發(fā)數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
封面圖片介紹
7.2 無(wú)鎖數(shù)據(jù)結(jié)構(gòu)的例子
8.6 本章總結(jié)
8.1 線程間劃分工作的技術(shù)
4.2 使用期望等待一次性事件
8.4 設(shè)計(jì)并發(fā)代碼的注意事項(xiàng)
D.5 &lt;mutex&gt;頭文件
3.1 共享數(shù)據(jù)帶來(lái)的問(wèn)題
資源
9.3 本章總結(jié)
10.3 本章總結(jié)
10.1 與并發(fā)相關(guān)的錯(cuò)誤類型
D.4 &lt;future&gt;頭文件
3.2 使用互斥量保護(hù)共享數(shù)據(jù)
9.1 線程池
1.1 何謂并發(fā)
9.2 中斷線程
4.4 使用同步操作簡(jiǎn)化代碼
A.2 刪除函數(shù)
1.3 C++中的并發(fā)和多線程
1.4 開(kāi)始入門
第5章 C++內(nèi)存模型和原子類型操作
消息傳遞框架與完整的ATM示例
8.2 影響并發(fā)代碼性能的因素
7.1 定義和意義
D.6 &lt;ratio&gt;頭文件
A.4 常量表達(dá)式函數(shù)
7.4 本章總結(jié)
1.5 本章總結(jié)
第3章 線程間共享數(shù)據(jù)

1.2 為什么使用并發(fā)?

主要原因有兩個(gè):關(guān)注點(diǎn)分離(SOC)和性能。事實(shí)上,它們應(yīng)該是使用并發(fā)的唯一原因;如果你觀察得足夠仔細(xì),所有因素都可以歸結(jié)到其中的一個(gè)原因(或者可能是兩個(gè)都有。當(dāng)然,除了像“就因?yàn)槲以敢狻边@樣的原因之外)。

1.2.1 為了分離關(guān)注點(diǎn)

編寫軟件時(shí),分離關(guān)注點(diǎn)是個(gè)好主意;通過(guò)將相關(guān)的代碼與無(wú)關(guān)的代碼分離,可以使程序更容易理解和測(cè)試,從而減少出錯(cuò)的可能性。即使一些功能區(qū)域中的操作需要在同一時(shí)刻發(fā)生的情況下,依舊可以使用并發(fā)分離不同的功能區(qū)域;若不顯式地使用并發(fā),就得編寫一個(gè)任務(wù)切換框架,或者在操作中主動(dòng)地調(diào)用一段不相關(guān)的代碼。

考慮一個(gè)有用戶界面的處理密集型應(yīng)用——DVD播放程序。這樣的應(yīng)用程序,應(yīng)具備這兩種功能:一,要從光盤中讀出數(shù)據(jù),對(duì)圖像和聲音進(jìn)行解碼,之后把解碼出的信號(hào)輸出至視頻和音頻硬件,從而實(shí)現(xiàn)DVD的無(wú)誤播放;二,還需要接受來(lái)自用戶的輸入,當(dāng)用戶單擊“暫?!?、“返回菜單”或“退出”按鍵的時(shí)候執(zhí)行對(duì)應(yīng)的操作。當(dāng)應(yīng)用是單個(gè)線程時(shí),應(yīng)用需要在回放期間定期檢查用戶的輸入,這就需要把“DVD播放”代碼和“用戶界面”代碼放在一起,以便調(diào)用。如果使用多線程方式來(lái)分隔這些關(guān)注點(diǎn),“用戶界面”代碼和“DVD播放”代碼就不再需要放在一起:一個(gè)線程可以處理“用戶界面”事件,另一個(gè)進(jìn)行“DVD播放”。它們之間會(huì)有交互(用戶點(diǎn)擊“暫?!?,不過(guò)任務(wù)間需要人為的進(jìn)行關(guān)聯(lián)。

這會(huì)給響應(yīng)性帶來(lái)一些錯(cuò)覺(jué),因?yàn)橛脩艚缑婢€程通常可以立即響應(yīng)用戶的請(qǐng)求,在當(dāng)請(qǐng)求傳達(dá)給忙碌線程,這時(shí)的相應(yīng)可以是簡(jiǎn)單地顯示代表忙碌的光標(biāo)或“請(qǐng)等待”字樣的消息。類似地,獨(dú)立的線程通常用來(lái)執(zhí)行那些必須在后臺(tái)持續(xù)運(yùn)行的任務(wù),例如,桌面搜索程序中監(jiān)視文件系統(tǒng)變化的任務(wù)。因?yàn)樗鼈冎g的交互清晰可辨,所以這種方式會(huì)使每個(gè)線程的邏輯變的更加簡(jiǎn)單。

在這種情況下,線程的數(shù)量不再依賴CPU中的可用內(nèi)核的數(shù)量,因?yàn)閷?duì)線程的劃分是基于概念上的設(shè)計(jì),而不是一種增加吞吐量的嘗試。

1.2.2 為了性能

多處理器系統(tǒng)已經(jīng)存在了幾十年,但直到最近,它們也只在超級(jí)計(jì)算機(jī)、大型機(jī)和大型服務(wù)器系統(tǒng)中才能看到。然而,芯片制造商越來(lái)越傾向于多核芯片的設(shè)計(jì),即在單個(gè)芯片上集成2、4、16或更多的處理器,從而獲取更好的性能。因此,多核臺(tái)式計(jì)算機(jī)、多核嵌入式設(shè)備,現(xiàn)在越來(lái)越普遍。它們計(jì)算能力的提高不是源自使單一任務(wù)運(yùn)行的更快,而是并行運(yùn)行多個(gè)任務(wù)。在過(guò)去,程序員曾坐看他們的程序隨著處理器的更新?lián)Q代而變得更快,無(wú)需他們這邊做任何事。但是現(xiàn)在,就像Herb Sutter所說(shuō)的,“沒(méi)有免費(fèi)的午餐了?!盵1] 如果想要利用日益增長(zhǎng)的計(jì)算能力,那就必須設(shè)計(jì)多任務(wù)并發(fā)式軟件。程序員必須留意這個(gè),尤其是那些迄今都忽略并發(fā)的人們,現(xiàn)在很有必要將其加入工具箱中了。

兩種方式利用并發(fā)提高性能:第一,將一個(gè)單個(gè)任務(wù)分成幾部分,且各自并行運(yùn)行,從而降低總運(yùn)行時(shí)間。這就是任務(wù)并行(task parallelism)。雖然這聽(tīng)起來(lái)很直觀,但它是一個(gè)相當(dāng)復(fù)雜的過(guò)程,因?yàn)樵诟鱾€(gè)部分之間可能存在著依賴。區(qū)別可能是在過(guò)程方面——一個(gè)線程執(zhí)行算法的一部分,而另一個(gè)線程執(zhí)行算法的另一個(gè)部分——或是在數(shù)據(jù)方面——每個(gè)線程在不同的數(shù)據(jù)部分上執(zhí)行相同的操作(第二種方式)。后一種方法被稱為數(shù)據(jù)并行(data parallelism)。

第一種并行方式影響的算法常被稱為易并行(embarrassingly parallel)算法。盡管易并行算法的代碼會(huì)讓你感覺(jué)到頭痛,但這對(duì)于你來(lái)說(shuō)是一件好事:我曾遇到過(guò)自然并行(naturally parallel)和便利并發(fā)(conveniently concurrent)的算法。易并行算法具有良好的可擴(kuò)展特性——當(dāng)可用硬件線程的數(shù)量增加時(shí),算法的并行性也會(huì)隨之增加。這種算法能很好的體現(xiàn)人多力量大。如果算法中有不易并行的部分,你可以把算法劃分成固定(不可擴(kuò)展)數(shù)量的并行任務(wù)。第8章將會(huì)再來(lái)討論,在線程之間劃分任務(wù)的技巧。

第二種方法是使用可并行的方式,來(lái)解決更大的問(wèn)題;與其同時(shí)處理一個(gè)文件,不如酌情處理2個(gè)、10個(gè)或20個(gè)。雖然,這是數(shù)據(jù)并行的一種應(yīng)用(通過(guò)對(duì)多組數(shù)據(jù)同時(shí)執(zhí)行相同的操作),但著重點(diǎn)不同。處理一個(gè)數(shù)據(jù)塊仍然需要同樣的時(shí)間,但在相同的時(shí)間內(nèi)處理了更多的數(shù)據(jù)。當(dāng)然,這種方法也有限制,并非在所有情況下都是有益的。不過(guò),這種方法所帶來(lái)的吞吐量提升,可以讓某些新功能成為可能,例如,可以并行處理圖片的各部分,就能提高視頻的分辨率。

1.2.3 什么時(shí)候不使用并發(fā)

知道何時(shí)不使用并發(fā)與知道何時(shí)使用它一樣重要?;旧希皇褂貌l(fā)的唯一原因就是,收益比不上成本。使用并發(fā)的代碼在很多情況下難以理解,因此編寫和維護(hù)的多線程代碼就會(huì)產(chǎn)生直接的腦力成本,同時(shí)額外的復(fù)雜性也可能引起更多的錯(cuò)誤。除非潛在的性能增益足夠大或關(guān)注點(diǎn)分離地足夠清晰,能抵消所需的額外的開(kāi)發(fā)時(shí)間以及與維護(hù)多線程代碼相關(guān)的額外成本(代碼正確的前提下);否則,別用并發(fā)。

同樣地,性能增益可能會(huì)小于預(yù)期;因?yàn)椴僮飨到y(tǒng)需要分配內(nèi)核相關(guān)資源和堆??臻g,所以在啟動(dòng)線程時(shí)存在固有的開(kāi)銷,然后才能把新線程加入調(diào)度器中,所有這一切都需要時(shí)間。如果在線程上的任務(wù)完成得很快,那么任務(wù)實(shí)際執(zhí)行的時(shí)間要比啟動(dòng)線程的時(shí)間小很多,這就會(huì)導(dǎo)致應(yīng)用程序的整體性能還不如直接使用“產(chǎn)生線程”的方式。

此外,線程是有限的資源。如果讓太多的線程同時(shí)運(yùn)行,則會(huì)消耗很多操作系統(tǒng)資源,從而使得操作系統(tǒng)整體上運(yùn)行得更加緩慢。不僅如此,因?yàn)槊總€(gè)線程都需要一個(gè)獨(dú)立的堆??臻g,所以運(yùn)行太多的線程也會(huì)耗盡進(jìn)程的可用內(nèi)存或地址空間。對(duì)于一個(gè)可用地址空間為4GB(32bit)的平坦架構(gòu)的進(jìn)程來(lái)說(shuō),這的確是個(gè)問(wèn)題:如果每個(gè)線程都有一個(gè)1MB的堆棧(很多系統(tǒng)都會(huì)這樣分配),那么4096個(gè)線程將會(huì)用盡所有地址空間,不會(huì)給代碼、靜態(tài)數(shù)據(jù)或者堆數(shù)據(jù)留有任何空間。即便64位(或者更大)的系統(tǒng)不存在這種直接的地址空間限制,但其他資源有限:如果你運(yùn)行了太多的線程,最終也是出會(huì)問(wèn)題的。盡管線程池(參見(jiàn)第9章)可以用來(lái)限制線程的數(shù)量,但這也并不是什么靈丹妙藥,它也有自己的問(wèn)題。

當(dāng)客戶端/服務(wù)器(C/S)應(yīng)用在服務(wù)器端為每一個(gè)鏈接啟動(dòng)一個(gè)獨(dú)立的線程,對(duì)于少量的鏈接是可以正常工作的,但當(dāng)同樣的技術(shù)用于需要處理大量鏈接的高需求服務(wù)器時(shí),也會(huì)因?yàn)榫€程太多而耗盡系統(tǒng)資源。在這種場(chǎng)景下,使用線程池可以對(duì)性能產(chǎn)生優(yōu)化(參見(jiàn)第9章)。

最后,運(yùn)行越多的線程,操作系統(tǒng)就需要做越多的上下文切換,每一次切換都需要耗費(fèi)本可以花在有價(jià)值工作上的時(shí)間。所以在某些時(shí)候,增加一個(gè)額外的線程實(shí)際上會(huì)降低,而非提高應(yīng)用程序的整體性能。為此,如果你試圖得到系統(tǒng)的最佳性能,可以考慮使用硬件并發(fā)(或不用),并調(diào)整運(yùn)行線程的數(shù)量。

為性能而使用并發(fā)就像所有其他優(yōu)化策略一樣:它擁有大幅度提高應(yīng)用性能的潛力,但它也可能使代碼復(fù)雜化,使其更難理解,并更容易出錯(cuò)。因此,只有應(yīng)用中具有顯著增益潛力的性能關(guān)鍵部分,才值得并發(fā)化。當(dāng)然,如果性能收益的潛力僅次于設(shè)計(jì)清晰或關(guān)注點(diǎn)分離,可能也值得使用多線程設(shè)計(jì)。

假設(shè)你已經(jīng)決定確實(shí)要在應(yīng)用中使用并發(fā),無(wú)論是為了性能、關(guān)注點(diǎn)分離,亦或是因?yàn)?em>多線程星期一(multithreading Monday)(譯者:可能是學(xué)習(xí)多線程的意思)。

問(wèn)題又來(lái)了,對(duì)于C++程序員來(lái)說(shuō),多線程意味著什么?


[1] “The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software,” Herb Sutter, Dr. Dobb’s Journal, 30(3), March 2005. http://www.gotw.ca/publications/concurrency-ddj.htm.