使用期望值的函數(shù)式編程
函數(shù)式編程(Functional Programming)是一種編程范式。在函數(shù)式編程中,函數(shù)被視為第一類(lèi)對(duì)象,可以作為參數(shù)傳遞給其他函數(shù),也可以作為返回值返回。函數(shù)式編程的核心思想是避免可變狀態(tài)和副作用,強(qiáng)調(diào)使用純函數(shù)進(jìn)行計(jì)算。純函數(shù)是指輸入相同,輸出也必定相同,并且沒(méi)有任何副作用的函數(shù)。這種特性使得函數(shù)式編程更容易進(jìn)行推理和測(cè)試,也更容易實(shí)現(xiàn)并發(fā)編程。
在C++中,期望值對(duì)象可以在線程間互相傳遞, 并允許計(jì)算結(jié)果依賴(lài)于另外一個(gè),而非對(duì)共享數(shù)據(jù)的顯式訪問(wèn)——這使函數(shù)式編程模式并發(fā)化(FP-style concurrency)的實(shí)現(xiàn)變得容易。
首先來(lái)看一個(gè)FP模式版的快速排序。

在創(chuàng)建new_lower和new_higher時(shí),std::move用于將lower_part和input的所有權(quán)轉(zhuǎn)移到遞歸調(diào)用的函數(shù)中。通過(guò)這種方式,可以避免對(duì)這些對(duì)象進(jìn)行拷貝操作,而只是在遞歸調(diào)用中使用原始對(duì)象的資源。當(dāng)傳遞一個(gè)對(duì)象作為參數(shù)進(jìn)行函數(shù)調(diào)用時(shí),通常會(huì)觸發(fā)拷貝構(gòu)造函數(shù)或移動(dòng)構(gòu)造函數(shù)。使用std::move可以明確指示我們希望轉(zhuǎn)移對(duì)象的所有權(quán),而不進(jìn)行拷貝構(gòu)造。這對(duì)于容器等需要大量數(shù)據(jù)移動(dòng)的對(duì)象來(lái)說(shuō),可以帶來(lái)顯著的性能提升。
FP模式中,期望值很容易轉(zhuǎn)化為并行版本。下面是FP模式線程強(qiáng)化版的快速排序。

這里最大的變化是,當(dāng)前線程不對(duì)小于中間值部分的列表進(jìn)行排序,使用std::async在另一線程對(duì)其進(jìn)行排序。大于部分則和之前一樣,使用遞歸的方式進(jìn)行排序。通過(guò)遞歸調(diào)用parallel_quick_sort,就可以利用硬件并發(fā)了。std::async會(huì)啟動(dòng)一個(gè)新線程,當(dāng)遞歸三次時(shí),就會(huì)有八個(gè)線程在運(yùn)行。
在這里,每個(gè)遞歸調(diào)用都創(chuàng)建了一個(gè)新的線程,并且通過(guò)異步任務(wù)進(jìn)行并發(fā)計(jì)算。每個(gè)線程獨(dú)立地操作自己的數(shù)據(jù),沒(méi)有共享的可變數(shù)據(jù),避免了線程之間的競(jìng)爭(zhēng)條件和同步問(wèn)題,減少了并發(fā)編程中常見(jiàn)的錯(cuò)誤和復(fù)雜性。盡管線程之間沒(méi)有共享的可變數(shù)據(jù),但是通過(guò)通信通道(std::future)來(lái)傳遞數(shù)據(jù)和結(jié)果。這種通信方式允許信息在不同線程之間傳遞,實(shí)現(xiàn)了線程之間的協(xié)作。