偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一文帶你領(lǐng)略并發(fā)編程的內(nèi)功心法

開發(fā) 后端
并發(fā)模型其實和分布式系統(tǒng)模型非常相似,在并發(fā)模型中是線程彼此進(jìn)行通信,而在分布式系統(tǒng)模型中是 進(jìn)程 彼此進(jìn)行通信。然而本質(zhì)上,進(jìn)程和線程也非常相似。這也就是為什么并發(fā)模型和分布式模型非常相似的原因。

 [[336857]]

本篇文章我們來探討一下并發(fā)設(shè)計模型。

可以使用不同的并發(fā)模型來實現(xiàn)并發(fā)系統(tǒng),并發(fā)模型說的是系統(tǒng)中的線程如何協(xié)作完成并發(fā)任務(wù)。不同的并發(fā)模型以不同的方式拆分任務(wù),線程可以以不同的方式進(jìn)行通信和協(xié)作。

并發(fā)模型和分布式系統(tǒng)很相似

并發(fā)模型其實和分布式系統(tǒng)模型非常相似,在并發(fā)模型中是線程彼此進(jìn)行通信,而在分布式系統(tǒng)模型中是 進(jìn)程 彼此進(jìn)行通信。然而本質(zhì)上,進(jìn)程和線程也非常相似。這也就是為什么并發(fā)模型和分布式模型非常相似的原因。

分布式系統(tǒng)通常要比并發(fā)系統(tǒng)面臨更多的挑戰(zhàn)和問題比如進(jìn)程通信、網(wǎng)絡(luò)可能出現(xiàn)異常,或者遠(yuǎn)程機(jī)器掛掉等等。但是一個并發(fā)模型同樣面臨著比如 CPU 故障、網(wǎng)卡出現(xiàn)問題、硬盤出現(xiàn)問題等。

因為并發(fā)模型和分布式模型很相似,因此他們可以相互借鑒,例如用于線程分配的模型就類似于分布式系統(tǒng)環(huán)境中的負(fù)載均衡模型。

其實說白了,分布式模型的思想就是借鑒并發(fā)模型的基礎(chǔ)上推演發(fā)展來的。

認(rèn)識兩個狀態(tài)

并發(fā)模型的一個重要的方面是,線程是否應(yīng)該共享狀態(tài),是具有共享狀態(tài)還是獨(dú)立狀態(tài)。共享狀態(tài)也就意味著在不同線程之間共享某些狀態(tài)

狀態(tài)其實就是數(shù)據(jù),比如一個或者多個對象。當(dāng)線程要共享數(shù)據(jù)時,就會造成 競態(tài)條件 或者 死鎖 等問題。當(dāng)然,這些問題只是可能會出現(xiàn),具體實現(xiàn)方式取決于你是否安全的使用和訪問共享對象。

 

獨(dú)立的狀態(tài)表明狀態(tài)不會在多個線程之間共享,如果線程之間需要通信的話,他們可以訪問不可變的對象來實現(xiàn),這是一種最有效的避免并發(fā)問題的一種方式,如下圖所示

 

使用獨(dú)立狀態(tài)讓我們的設(shè)計更加簡單,因為只有一個線程能夠訪問對象,即使交換對象,也是不可變的對象。

并發(fā)模型

并行 Worker

第一個并發(fā)模型是并行 worker 模型,客戶端會把任務(wù)交給 代理人(Delegator),然后由代理人把工作分配給不同的 工人(worker)。如下圖所示

 

并行 worker 的核心思想是,它主要有兩個進(jìn)程即代理人和工人,Delegator 負(fù)責(zé)接收來自客戶端的任務(wù)并把任務(wù)下發(fā),交給具體的 Worker 進(jìn)行處理,Worker 處理完成后把結(jié)果返回給 Delegator,在 Delegator 接收到 Worker 處理的結(jié)果后對其進(jìn)行匯總,然后交給客戶端。

并行 Worker 模型是 Java 并發(fā)模型中非常常見的一種模型。許多 java.util.concurrent 包下的并發(fā)工具都使用了這種模型。

并行 Worker 的優(yōu)點

并行 Worker 模型的一個非常明顯的特點就是很容易理解,為了提高系統(tǒng)的并行度你可以增加多個 Worker 完成任務(wù)。

并行 Worker 模型的另外一個好處就是,它會將一個任務(wù)拆分成多個小任務(wù),并發(fā)執(zhí)行,Delegator 在接受到 Worker 的處理結(jié)果后就會返回給 Client,整個 Worker -> Delegator -> Client 的過程是異步的。

并行 Worker 的缺點

同樣的,并行 Worker 模式同樣會有一些隱藏的缺點

共享狀態(tài)會變得很復(fù)雜

實際的并行 Worker 要比我們圖中畫出的更復(fù)雜,主要是并行 Worker 通常會訪問內(nèi)存或共享數(shù)據(jù)庫中的某些共享數(shù)據(jù)。

 

 


 

 

這些共享狀態(tài)可能會使用一些工作隊列來保存業(yè)務(wù)數(shù)據(jù)、數(shù)據(jù)緩存、數(shù)據(jù)庫的連接池等。在線程通信中,線程需要確保共享狀態(tài)是否能夠讓其他線程共享,而不是僅僅停留在 CPU 緩存中讓自己可用,當(dāng)然這些都是程序員在設(shè)計時就需要考慮的問題。線程需要避免 競態(tài)條件,死鎖 和許多其他共享狀態(tài)造成的并發(fā)問題。

多線程在訪問共享數(shù)據(jù)時,會丟失并發(fā)性,因為操作系統(tǒng)要保證只有一個線程能夠訪問數(shù)據(jù),這會導(dǎo)致共享數(shù)據(jù)的爭用和搶占。未搶占到資源的線程會 阻塞。

現(xiàn)代的非阻塞并發(fā)算法可以減少爭用提高性能,但是非阻塞算法比較難以實現(xiàn)。

可持久化的數(shù)據(jù)結(jié)構(gòu)(Persistent data structures) 是另外一個選擇??沙志没臄?shù)據(jù)結(jié)構(gòu)在修改后始終會保留先前版本。因此,如果多個線程同時修改一個可持久化的數(shù)據(jù)結(jié)構(gòu),并且一個線程對其進(jìn)行了修改,則修改的線程會獲得對新數(shù)據(jù)結(jié)構(gòu)的引用。

雖然可持久化的數(shù)據(jù)結(jié)構(gòu)是一個新的解決方法,但是這種方法實行起來卻有一些問題,比如,一個持久列表會將新元素添加到列表的開頭,并返回所添加的新元素的引用,但是其他線程仍然只持有列表中先前的第一個元素的引用,他們看不到新添加的元素。

持久化的數(shù)據(jù)結(jié)構(gòu)比如 鏈表(LinkedList) 在硬件性能上表現(xiàn)不佳。列表中的每個元素都是一個對象,這些對象散布在計算機(jī)內(nèi)存中?,F(xiàn)代 CPU 的順序訪問往往要快的多,因此使用數(shù)組等順序訪問的數(shù)據(jù)結(jié)構(gòu)則能夠獲得更高的性能。CPU 高速緩存可以將一個大的矩陣塊加載到高速緩存中,并讓 CPU 在加載后直接訪問 CPU 高速緩存中的數(shù)據(jù)。對于鏈表,將元素分散在整個 RAM 上,這實際上是不可能的。

無狀態(tài)的 worker

共享狀態(tài)可以由其他線程所修改,因此,worker 必須在每次操作共享狀態(tài)時重新讀取,以確保在副本上能夠正確工作。不在線程內(nèi)部保持狀態(tài)的 worker 成為無狀態(tài)的 worker。

作業(yè)順序是不確定的

并行工作模型的另一個缺點是作業(yè)的順序不確定,無法保證首先執(zhí)行或最后執(zhí)行哪些作業(yè)。任務(wù) A 在任務(wù) B 之前分配給 worker,但是任務(wù) B 可能在任務(wù) A 之前執(zhí)行。

流水線

第二種并發(fā)模型就是我們經(jīng)常在生產(chǎn)車間遇到的 流水線并發(fā)模型,下面是流水線設(shè)計模型的流程圖

 

這種組織架構(gòu)就像是工廠中裝配線中的 worker,每個 worker 只完成全部工作的一部分,完成一部分后,worker 會將工作轉(zhuǎn)發(fā)給下一個 worker。

每道程序都在自己的線程中運(yùn)行,彼此之間不會共享狀態(tài),這種模型也被稱為無共享并發(fā)模型。

使用流水線并發(fā)模型通常被設(shè)計為非阻塞I/O,也就是說,當(dāng)沒有給 worker 分配任務(wù)時,worker 會做其他工作。非阻塞I/O 意味著當(dāng) worker 開始 I/O 操作,例如從網(wǎng)絡(luò)中讀取文件,worker 不會等待 I/O 調(diào)用完成。因為 I/O 操作很慢,所以等待 I/O 非常耗費(fèi)時間。在等待 I/O 的同時,CPU 可以做其他事情,I/O 操作完成后的結(jié)果將傳遞給下一個 worker。下面是非阻塞 I/O 的流程圖

 

在實際情況中,任務(wù)通常不會按著一條裝配線流動,由于大多數(shù)程序需要做很多事情,因此需要根據(jù)完成的不同工作在不同的 worker 之間流動,如下圖所示

 

任務(wù)還可能需要多個 worker 共同參與完成

 

響應(yīng)式 - 事件驅(qū)動系統(tǒng)

使用流水線模型的系統(tǒng)有時也被稱為 響應(yīng)式 或者 事件驅(qū)動系統(tǒng),這種模型會根據(jù)外部的事件作出響應(yīng),事件可能是某個 HTTP 請求或者某個文件完成加載到內(nèi)存中。

Actor 模型

在 Actor 模型中,每一個 Actor 其實就是一個 Worker, 每一個 Actor 都能夠處理任務(wù)。

簡單來說,Actor 模型是一個并發(fā)模型,它定義了一系列系統(tǒng)組件應(yīng)該如何動作和交互的通用規(guī)則,最著名的使用這套規(guī)則的編程語言是 Erlang。一個參與者Actor對接收到的消息做出響應(yīng),然后可以創(chuàng)建出更多的 Actor 或發(fā)送更多的消息,同時準(zhǔn)備接收下一條消息。

 

Channels 模型

在 Channel 模型中,worker 通常不會直接通信,與此相對的,他們通常將事件發(fā)送到不同的 通道(Channel)上,然后其他 worker 可以在這些通道上獲取消息,下面是 Channel 的模型圖

 

有的時候 worker 不需要明確知道接下來的 worker 是誰,他們只需要將作者寫入通道中,監(jiān)聽 Channel 的 worker 可以訂閱或者取消訂閱,這種方式降低了 worker 和 worker 之間的耦合性。

流水線設(shè)計的優(yōu)點

與并行設(shè)計模型相比,流水線模型具有一些優(yōu)勢,具體優(yōu)勢如下

不會存在共享狀態(tài)

因為流水線設(shè)計能夠保證 worker 在處理完成后再傳遞給下一個 worker,所以 worker 與 worker 之間不需要共享任何狀態(tài),也就不用無需考慮以為并發(fā)而引起的并發(fā)問題。你甚至可以在實現(xiàn)上把每個 worker 看成是單線程的一種。

有狀態(tài) worker

因為 worker 知道沒有其他線程修改自身的數(shù)據(jù),所以流水線設(shè)計中的 worker 是有狀態(tài)的,有狀態(tài)的意思是他們可以將需要操作的數(shù)據(jù)保留在內(nèi)存中,有狀態(tài)通常比無狀態(tài)更快。

更好的硬件整合

因為你可以把流水線看成是單線程的,而單線程的工作優(yōu)勢在于它能夠和硬件的工作方式相同。因為有狀態(tài)的 worker 通常在 CPU 中緩存數(shù)據(jù),這樣可以更快地訪問緩存的數(shù)據(jù)。

使任務(wù)更加有效的進(jìn)行

可以對流水線并發(fā)模型中的任務(wù)進(jìn)行排序,一般用來日志的寫入和恢復(fù)。

流水線設(shè)計的缺點

流水線并發(fā)模型的缺點是任務(wù)會涉及多個 worker,因此可能會分散在項目代碼的多個類中。因此很難確定每個 worker 都在執(zhí)行哪個任務(wù)。流水線的代碼編寫也比較困難,設(shè)計許多嵌套回調(diào)處理程序的代碼通常被稱為 回調(diào)地獄?;卣{(diào)地獄很難追蹤 debug。

函數(shù)性并行

函數(shù)性并行模型是最近才提出的一種并發(fā)模型,它的基本思路是使用函數(shù)調(diào)用來實現(xiàn)。消息的傳遞就相當(dāng)于是函數(shù)的調(diào)用。傳遞給函數(shù)的參數(shù)都會被拷貝,因此在函數(shù)之外的任何實體都無法操縱函數(shù)內(nèi)的數(shù)據(jù)。這使得函數(shù)執(zhí)行類似于原子操作。每個函數(shù)調(diào)用都可以獨(dú)立于任何其他函數(shù)調(diào)用執(zhí)行。

當(dāng)每個函數(shù)調(diào)用獨(dú)立執(zhí)行時,每個函數(shù)都可以在單獨(dú)的 CPU 上執(zhí)行。這也就是說,函數(shù)式并行并行相當(dāng)于是各個 CPU 單獨(dú)執(zhí)行各自的任務(wù)。

JDK 1.7 中的 ForkAndJoinPool 類就實現(xiàn)了函數(shù)性并行的功能。Java 8 提出了 stream 的概念,使用并行流也能夠?qū)崿F(xiàn)大量集合的迭代。

函數(shù)性并行的難點是要知道函數(shù)的調(diào)用流程以及哪些 CPU 執(zhí)行了哪些函數(shù),跨 CPU 函數(shù)調(diào)用會帶來額外的開銷。

本文轉(zhuǎn)載自微信公眾號「Java建設(shè)者」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Java建設(shè)者公眾號。

 

責(zé)任編輯:武曉燕 來源: Java建設(shè)者
相關(guān)推薦

2020-11-10 09:20:40

開發(fā)模式代碼

2019-08-06 09:00:00

JavaScript函數(shù)式編程前端

2023-12-21 17:11:21

Containerd管理工具命令行

2022-12-20 07:39:46

2023-11-20 08:18:49

Netty服務(wù)器

2023-07-31 08:18:50

Docker參數(shù)容器

2021-05-29 10:11:00

Kafa數(shù)據(jù)業(yè)務(wù)

2022-11-11 19:09:13

架構(gòu)

2023-11-06 08:16:19

APM系統(tǒng)運(yùn)維

2022-02-24 07:34:10

SSL協(xié)議加密

2023-10-27 08:15:45

2023-11-08 08:15:48

服務(wù)監(jiān)控Zipkin

2019-06-13 21:31:19

AI

2024-05-22 09:45:49

2021-09-13 22:34:56

區(qū)塊鏈新基建數(shù)字化轉(zhuǎn)型

2023-03-06 21:29:41

mmap技術(shù)操作系統(tǒng)

2020-11-27 09:40:53

Rollup前端代碼

2022-04-08 09:01:14

CSS自定義屬性前端

2022-05-16 10:49:28

網(wǎng)絡(luò)協(xié)議數(shù)據(jù)

2025-04-28 02:22:00

點贊
收藏

51CTO技術(shù)棧公眾號