溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

golang中的并發(fā)介紹

發(fā)布時(shí)間:2020-06-24 10:17:53 來源:億速云 閱讀:141 作者:Leah 欄目:編程語言

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)golang中的并發(fā)介紹,以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

正如過程式編程和面向?qū)ο笠粯?,一個(gè)好的編程模式需要有一個(gè)極其簡潔的內(nèi)核,還有在此之上豐富的外延,可以解決現(xiàn)實(shí)世界中各種各樣的問題。本文以GO語言為例,解釋其中內(nèi)核、外延。

并發(fā)模式之內(nèi)核

這種并發(fā)模式的內(nèi)核只需要協(xié)程和通道就夠了。其中協(xié)程負(fù)責(zé)執(zhí)行代碼,通道負(fù)責(zé)在協(xié)程之間傳遞事件。

golang中的并發(fā)介紹

并發(fā)編程一直以來都是個(gè)非常困難的工作。要想編寫一個(gè)良好的并發(fā)程序,我們不得不了解線程, 鎖,semaphore,barrier甚至CPU更新高速緩存的方式,而且他們個(gè)個(gè)都有怪脾氣,處處是陷阱。筆者除非萬不得以,決不會自己操作這些底層 并發(fā)元素。一個(gè)簡潔的并發(fā)模式不需要這些復(fù)雜的底層元素,只需協(xié)程和通道就夠了。

協(xié)程是輕量級的線程。在過程式編程中,當(dāng)調(diào)用一個(gè)過程的時(shí)候,需要等待其執(zhí)行完才返回。而調(diào)用一個(gè)協(xié)程的時(shí)候,不需要等待其執(zhí)行完,會立即返回。

協(xié)程十分輕量,Go語言可以在一個(gè)進(jìn)程中執(zhí)行有數(shù)以十萬計(jì)的協(xié)程,依舊保持高性能。而對于普通的平臺,一個(gè)進(jìn)程有數(shù)千個(gè)線程,其CPU會忙于上下文切換,性能急劇下降。隨意創(chuàng)建線程可不是一個(gè)好主意,但是我們可以大量使用的協(xié)程。

通道是協(xié)程之間的數(shù)據(jù)傳輸通道。通道可以在眾多的協(xié)程之間傳遞數(shù)據(jù),具體可以值也可以是個(gè)引用。通道有兩種使用方式。

協(xié)程可以試圖向通道放入數(shù)據(jù),如果通道滿了,會掛起協(xié)程,直到通道可以為他放入數(shù)據(jù)為止。

協(xié)程可以試圖向通道索取數(shù)據(jù),如果通道沒有數(shù)據(jù),會掛起協(xié)程,直到通道返回?cái)?shù)據(jù)為止。

如此,通道就可以在傳遞數(shù)據(jù)的同時(shí),控制協(xié)程的運(yùn)行。有點(diǎn)像事件驅(qū)動,也有點(diǎn)像阻塞隊(duì)列。這兩個(gè)概念非常的簡單,各個(gè)語言平臺都會有相應(yīng)的實(shí)現(xiàn)。在Java和C上也各有庫可以實(shí)現(xiàn)兩者。

golang中的并發(fā)介紹

只要有協(xié)程和通道,就可以優(yōu)雅的解決并發(fā)的問題。不必使用其他和并發(fā)有關(guān)的概念。那如何用這兩把利刃解決各式各樣的實(shí)際問題呢?

并發(fā)模式之外延

協(xié)程相較于線程,可以大量創(chuàng)建。打開這扇門,我們拓展出新的用法,可以做生成器,可以讓函數(shù)返回“服務(wù)”,可以讓循環(huán)并發(fā)執(zhí)行,還能共享變量。但是出現(xiàn)新 的用法的同時(shí),也帶來了新的棘手問題,協(xié)程也會泄漏,不恰當(dāng)?shù)氖褂脮绊懶阅?。下面會逐一介紹各種用法和問題。演示的代碼用GO語言寫成,因?yàn)槠浜啙嵜?了,而且支持全部功能。

1、生成器

有的時(shí)候,我們需要有一個(gè)函數(shù)能不斷生成數(shù)據(jù)。比方說這個(gè)函數(shù)可以讀文件,讀網(wǎng)絡(luò),生成自增長序列,生成隨機(jī)數(shù)。這些行為的特點(diǎn)就是,函數(shù)的已知一些變量,如文件路徑。然后不斷調(diào)用,返回新的數(shù)據(jù)。

golang中的并發(fā)介紹

下面生成隨機(jī)數(shù)為例,以讓我們做一個(gè)會并發(fā)執(zhí)行的隨機(jī)數(shù)生成器。

// 函數(shù)rand_generator_1 ,返回 int
funcrand_generator_1() int {
         return rand.Int()
}
//        上面是一個(gè)函數(shù),返回一個(gè)int。假如rand.Int()這個(gè)函數(shù)調(diào)用需要很長時(shí)間等待,那該函數(shù)的調(diào)用者也會因此而掛起。所以我們可以創(chuàng)建一個(gè)協(xié)程,專門執(zhí)行rand.Int()。


// 函數(shù)rand_generator_2,返回通道(Channel)
funcrand_generator_2() chan int {
         // 創(chuàng)建通道
         out := make(chan int)
         // 創(chuàng)建協(xié)程
         go func() {
                  for {
                           //向通道內(nèi)寫入數(shù)據(jù),如果無人讀取會等待
                            out <- rand.Int()
                   }
         }()
         return out
} 
funcmain() {
         // 生成隨機(jī)數(shù)作為一個(gè)服務(wù)
         rand_service_handler :=rand_generator_2()
         // 從服務(wù)中讀取隨機(jī)數(shù)并打印
         fmt.Printf("%d\n",<-rand_service_handler)
}

上面的這段函數(shù)就可以并發(fā)執(zhí)行了rand.Int()。有一點(diǎn)值得注意到函數(shù)的返回可以理解為一個(gè)“服務(wù)”。但我們需要獲取隨機(jī)數(shù)據(jù)時(shí)候,可以隨時(shí)向這個(gè) 服務(wù)取用,他已經(jīng)為我們準(zhǔn)備好了相應(yīng)的數(shù)據(jù),無需等待,隨要隨到。

如果我們調(diào)用這個(gè)服務(wù)不是很頻繁,一個(gè)協(xié)程足夠滿足我們的需求了。但如果我們需要大量訪問,怎么辦?我們可以用下面介紹的多路復(fù)用技術(shù),啟動若干生成器,再將其整合成一個(gè)大的服務(wù)。

調(diào)用生成器,可以返回一個(gè)“服務(wù)”??梢杂迷诔掷m(xù)獲取數(shù)據(jù)的場合。用途很廣泛,讀取數(shù)據(jù),生成ID,甚至定時(shí)器。這是一種非常簡潔的思路,將程     序并發(fā)化。

2、多路復(fù)用

多路復(fù)用是讓一次處理多個(gè)隊(duì)列的技術(shù)。Apache使用處理每個(gè)連接都需要一個(gè)進(jìn)程,所以其并發(fā)性能不是很好。而Nginx使用多路復(fù)用的技術(shù),讓一 個(gè)進(jìn)程處理多個(gè)連接,所以并發(fā)性能比較好。

同樣,在協(xié)程的場合,多路復(fù)用也是需要的,但又有所不同。多路復(fù)用可以將若干個(gè)相似的小服務(wù)整合成一個(gè)大服務(wù)。

golang中的并發(fā)介紹

那么讓我們用多路復(fù)用技術(shù)做一個(gè)更高并發(fā)的隨機(jī)數(shù)生成器吧。

// 函數(shù)rand_generator_3 ,返回通道(Channel)
         funcrand_generator_3() chan int {
         // 創(chuàng)建兩個(gè)隨機(jī)數(shù)生成器服務(wù)
         rand_generator_1 := rand_generator_2()
         rand_generator_2 := rand_generator_2()
         //創(chuàng)建通道
         out := make(chan int)
          //創(chuàng)建協(xié)程
         go func() {
                   for {
                           //讀取生成器1中的數(shù)據(jù),整合
                           out <-<-rand_generator_1
                   }
         }()
         go func() {
                   for {
                            //讀取生成器2中的數(shù)據(jù),整合
                            out <-<-rand_generator_2
                   }
         }()
         return out
}

上面是使用了多路復(fù)用技術(shù)的高并發(fā)版的隨機(jī)數(shù)生成器。通過整合兩個(gè)隨機(jī)數(shù)生成器,這個(gè)版本的能力是剛才的兩倍。雖然協(xié)程可以大量創(chuàng)建,但是眾多協(xié)程還是會爭搶輸出的通道。

Go語言提供了Select關(guān)鍵字來解決,各家也有各家竅門。加大輸出通道的緩沖大小是個(gè)通用的解決方法。

多路復(fù)用技術(shù)可以用來整合多個(gè)通道。提升性能和操作的便捷。配合其他的模式使用有很大的威力。

3、Future技術(shù)

Future是一個(gè)很有用的技術(shù),我們常常使用Future來操作線程。我們可以在使用線程的時(shí)候,可以創(chuàng)建一個(gè)線程,返回Future,之后可以通過它等待結(jié)果。  但是在協(xié)程環(huán)境下的Future可以更加徹底,輸入?yún)?shù)同樣可以是Future的。

golang中的并發(fā)介紹

調(diào)用一個(gè)函數(shù)的時(shí)候,往往是參數(shù)已經(jīng)準(zhǔn)備好了。調(diào)用協(xié)程的時(shí)候也同樣如此。但是如果我們將傳入的參 數(shù)設(shè)為通道,這樣我們就可以在不準(zhǔn)備好參數(shù)的情況下調(diào)用函數(shù)。這樣的設(shè)計(jì)可以提供很大的自由度和并發(fā)度。函數(shù)調(diào)用和函數(shù)參數(shù)準(zhǔn)備這兩個(gè)過程可以完全解耦。 下面舉一個(gè)用該技術(shù)訪問數(shù)據(jù)庫的例子。

//一個(gè)查詢結(jié)構(gòu)體
typequery struct {
         //參數(shù)Channel
         sql chan string
         //結(jié)果Channel
         result chan string
}
//執(zhí)行Query
funcexecQuery(q query) {
         //啟動協(xié)程
         go func() {
                   //獲取輸入
                   sql := <-q.sql
                   //訪問數(shù)據(jù)庫,輸出結(jié)果通道
                   q.result <- "get" + sql
         }()
}
funcmain() {
         //初始化Query
         q :=
                   query{make(chan string, 1),make(chan string, 1)}
         //執(zhí)行Query,注意執(zhí)行的時(shí)候無需準(zhǔn)備參數(shù)
         execQuery(q)
         //準(zhǔn)備參數(shù)
         q.sql <- "select * fromtable"
         //獲取結(jié)果
         fmt.Println(<-q.result)
}

上面利用Future技術(shù),不單讓結(jié)果在Future獲得,參數(shù)也是在Future獲取。準(zhǔn)備好參數(shù)后,自動執(zhí)行。Future和生成器的區(qū)別在 于,F(xiàn)uture返回一個(gè)結(jié)果,而生成器可以重復(fù)調(diào)用。還有一個(gè)值得注意的地方,就是將參數(shù)Channel和結(jié)果Channel定義在一個(gè)結(jié)構(gòu)體里面作為 參數(shù),而不是返回結(jié)果Channel。這樣做可以增加聚合度,好處就是可以和多路復(fù)用技術(shù)結(jié)合起來使用。

Future技術(shù)可以和各個(gè)其他技術(shù)組合起來用??梢酝ㄟ^多路復(fù)用技術(shù),監(jiān)聽多個(gè)結(jié)果Channel,當(dāng)有結(jié)果后,自動返回。也可以和生成器組合使用,生 成器不斷生產(chǎn)數(shù)據(jù),F(xiàn)uture技術(shù)逐個(gè)處理數(shù)據(jù)。Future技術(shù)自身還可以首尾相連,形成一個(gè)并發(fā)的pipe filter。這個(gè)pipe filter可以用于讀寫數(shù)據(jù)流,操作數(shù)據(jù)流。

Future是一個(gè)非常強(qiáng)大的技術(shù)手段。可以在調(diào)用的時(shí)候不關(guān)心數(shù)據(jù)是否準(zhǔn)備好,返回值是否計(jì)算好的問題。讓程序中的組件在準(zhǔn)備好數(shù)據(jù)的時(shí)候自動跑起來。

4、并發(fā)循環(huán)

循環(huán)往往是性能上的熱點(diǎn)。如果性能瓶頸出現(xiàn)在CPU上的話,那么九成可能性熱點(diǎn)是在一個(gè)循環(huán)體內(nèi)部。所以如果能讓循環(huán)體并發(fā)執(zhí)行,那么性能就會提高很多。

golang中的并發(fā)介紹

要并發(fā)循環(huán)很簡單,只有在每個(gè)循環(huán)體內(nèi)部啟動協(xié)程。協(xié)程作為循環(huán)體可以并發(fā)執(zhí)行。調(diào)用啟動前設(shè)置一個(gè)計(jì)數(shù)器,每一個(gè)循環(huán)體執(zhí)行完畢就在計(jì)數(shù)器上加一個(gè)元素,調(diào)用完成后通過監(jiān)聽計(jì)數(shù)器等待循環(huán)協(xié)程全部完成。

//建立計(jì)數(shù)器
sem :=make(chan int, N);
//FOR循環(huán)體
for i,xi:= range data {
         //建立協(xié)程
    go func (i int, xi float) {
        doSomething(i,xi);
                   //計(jì)數(shù)
        sem <- 0;
    } (i, xi);
}
// 等待循環(huán)結(jié)束
for i := 0; i < N; ++i {
 <-sem }

上面是一個(gè)并發(fā)循環(huán)例子。通過計(jì)數(shù)器來等待循環(huán)全部完成。如果結(jié)合上面提到的Future技術(shù)的話,則不必等待??梢缘鹊秸嬲枰慕Y(jié)果的地方,再去檢查數(shù)據(jù)是否完成。

通過并發(fā)循環(huán)可以提供性能,利用多核,解決CPU熱點(diǎn)。正因?yàn)閰f(xié)程可以大量創(chuàng)建,才能在循環(huán)體中如此使用,如果是使用線程的話,就需要引入線程池之類的東西,防止創(chuàng)建過多線程,而協(xié)程則簡單的多。

5、ChainFilter技術(shù)

前面提到了Future技術(shù)首尾相連,可以形成一個(gè)并發(fā)的pipe filter。這種方式可以做很多事情,如果每個(gè)Filter都由同一個(gè)函數(shù)組成,還可以有一種簡單的辦法把他們連起來。

golang中的并發(fā)介紹

由于每個(gè)Filter協(xié)程都可以并發(fā)運(yùn)行,這樣的結(jié)構(gòu)非常有利于多核環(huán)境。下面是一個(gè)例子,用這種模式來產(chǎn)生素?cái)?shù)。

// Aconcurrent prime sieve
packagemain
// Sendthe sequence 2, 3, 4, ... to channel 'ch'.
funcGenerate(ch chan<- int) {
         for i := 2; ; i++ {
                  ch<- i // Send 'i' to channel 'ch'.
         }
}
// Copythe values from channel 'in' to channel 'out',
//removing those divisible by 'prime'.
funcFilter(in <-chan int, out chan<- int, prime int) {
         for {
                   i := <-in // Receive valuefrom 'in'.
                   if i%prime != 0 {
                            out <- i // Send'i' to 'out'.
                   }
         }
}
// Theprime sieve: Daisy-chain Filter processes.
funcmain() {
         ch := make(chan int) // Create a newchannel.
         go Generate(ch)      // Launch Generate goroutine.
         for i := 0; i < 10; i++ {
                   prime := <-ch
                   print(prime, "\n")
                   ch2 := make(chan int)
                   go Filter(ch, ch2, prime)
                   ch = ch2
         }
}

上面的程序創(chuàng)建了10個(gè)Filter,每個(gè)分別過濾一個(gè)素?cái)?shù),所以可以輸出前10個(gè)素?cái)?shù)。

Chain-Filter通過簡單的代碼創(chuàng)建并發(fā)的過濾器鏈。這種辦法還有一個(gè)好處,就是每個(gè)通道只有兩個(gè)協(xié)程會訪問,就不會有激烈的競爭,性能會比較好

6、共享變量

協(xié)程之間的通信只能夠通過通道。但是我們習(xí)慣于共享變量,而且很多時(shí)候使用共享變量能讓代碼更簡潔。比如一個(gè)Server有兩個(gè)狀態(tài)開和關(guān)。其他僅僅希望獲取或改變其狀態(tài),那又該如何做呢??梢詫⑦@個(gè)變量至于0通道中,并使用一個(gè)協(xié)程來維護(hù)。

golang中的并發(fā)介紹

下面的例子描述如何用這個(gè)方式,實(shí)現(xiàn)一個(gè)共享變量。

//共享變量有一個(gè)讀通道和一個(gè)寫通道組成
typesharded_var struct {
         reader chan int
         writer chan int
}
//共享變量維護(hù)協(xié)程
funcsharded_var_whachdog(v sharded_var) {
         go func() {
                   //初始值
                   var value int = 0
                   for {
                            //監(jiān)聽讀寫通道,完成服務(wù)
                            select {
                            case value =<-v.writer:
                            case v.reader <-value:
                            }
                   }
         }()
}
funcmain() {
         //初始化,并開始維護(hù)協(xié)程
         v := sharded_var{make(chan int),make(chan int)}
         sharded_var_whachdog(v)
         //讀取初始值
         fmt.Println(<-v.reader)
         //寫入一個(gè)值
         v.writer <- 1
         //讀取新寫入的值
         fmt.Println(<-v.reader)
}

這樣,就可以在協(xié)程和通道的基礎(chǔ)上實(shí)現(xiàn)一個(gè)協(xié)程安全的共享變量了。定義一個(gè)寫通道,需要更新變量的時(shí)候,往里寫新的值。再定義一個(gè)讀通道,需要讀的時(shí)候,從里面讀。通過一個(gè)單獨(dú)的協(xié)程來維護(hù)這兩個(gè)通道。保證數(shù)據(jù)的一致性。

一般來說,協(xié)程之間不推薦使用共享變量來交互,但是按照這個(gè)辦法,在一些場合,使用共享變量也是可取的。很多平臺上有較為原生的共享變量支持,到底用那種 實(shí)現(xiàn)比較好,就見仁見智了。另外利用協(xié)程和通道,可以還實(shí)現(xiàn)各種常見的并發(fā)數(shù)據(jù)結(jié)構(gòu),如鎖等等,就不一一贅述。

7、協(xié)程泄漏

協(xié)程和內(nèi)存一樣,是系統(tǒng)的資源。對于內(nèi)存,有自動垃圾回收。但是對于協(xié)程,沒有相應(yīng)的回收機(jī)制。會不會若干年后,協(xié)程普及了,協(xié)程泄漏和內(nèi)存泄漏一樣成為 程序員永遠(yuǎn)的痛呢?

一般而言,協(xié)程執(zhí)行結(jié)束后就會銷毀。協(xié)程也會占用內(nèi)存,如果發(fā)生協(xié)程泄漏,影響和內(nèi)存泄漏一樣嚴(yán)重。輕則拖慢程序,重則壓垮機(jī)器。

C和C++都是沒有自動內(nèi)存回收的程序設(shè)計(jì)語言,但只要有良好的編程習(xí)慣,就能解決規(guī)避問題。對于協(xié)程是一樣的,只要有好習(xí)慣就可以了。

只有兩種情況會導(dǎo)致協(xié)程無法結(jié)束。一種情況是協(xié)程想從一個(gè)通道讀數(shù)據(jù),但無人往這個(gè)通道寫入數(shù)據(jù),或許這個(gè)通道已經(jīng)被遺忘了。還有一種情況是程想往一個(gè)通道寫數(shù)據(jù),可是由于無人監(jiān)聽這個(gè)通道,該協(xié)程將永遠(yuǎn)無法向下執(zhí)行。下面分別討論如何避免這兩種情況。

對于協(xié)程想從一個(gè)通道讀數(shù)據(jù),但無人往這個(gè)通道寫入數(shù)據(jù)這種情況。解決的辦法很簡單,加入超時(shí)機(jī)制。對于有不確定會不會返回的情況,必須加入超時(shí),避免出 現(xiàn)永久等待。

另外不一定要使用定時(shí)器才能終止協(xié)程。也可以對外暴露一個(gè)退出提醒通道。任何其他協(xié)程都可以通過該通道來提醒這個(gè)協(xié)程終止。

golang中的并發(fā)介紹

對于協(xié)程想往一個(gè)通道寫數(shù)據(jù),但通道阻塞無法寫入這種情況。解決的辦法也很簡單,就是給通道加緩沖。但前提是這個(gè)通道只會接收到固定數(shù)目的寫入。

比方說, 已知一個(gè)通道最多只會接收N次數(shù)據(jù),那么就將這個(gè)通道的緩沖設(shè)置為N。那么該通道將永遠(yuǎn)不會堵塞,協(xié)程自然也不會泄漏。也可以將其緩沖設(shè)置為無限,不過這 樣就要承擔(dān)內(nèi)存泄漏的風(fēng)險(xiǎn)了。等協(xié)程執(zhí)行完畢后,這部分通道內(nèi)存將會失去引用,會被自動垃圾回收掉。

funcnever_leak(ch chan int) {
         //初始化timeout,緩沖為1
         timeout := make(chan bool, 1)
         //啟動timeout協(xié)程,由于緩存為1,不可能泄露
         go func() {
                   time.Sleep(1 * time.Second)
                   timeout <- true
         }()
         //監(jiān)聽通道,由于設(shè)有超時(shí),不可能泄露
         select {
         case <-ch:
                   // a read from ch hasoccurred
         case <-timeout:
                   // the read from ch has timedout
         }
}

上面是個(gè)避免泄漏例子。使用超時(shí)避免讀堵塞,使用緩沖避免寫堵塞。

和內(nèi)存里面的對象一樣,對于長期存在的協(xié)程,我們不用擔(dān)心泄漏問題。一是長期存在,二是數(shù)量較少。要警惕的只有那些被臨時(shí)創(chuàng)建的協(xié)程,這些協(xié)程數(shù)量大且生 命周期短,往往是在循環(huán)中創(chuàng)建的,要應(yīng)用前面提到的辦法,避免泄漏發(fā)生。協(xié)程也是把雙刃劍,如果出問題,不但沒能提高程序性能,反而會讓程序崩潰。但就像 內(nèi)存一樣,同樣有泄漏的風(fēng)險(xiǎn),但越用越溜了。

并發(fā)模式之實(shí)現(xiàn)

在并發(fā)編程大行其道的今天,對協(xié)程和通道的支持成為各個(gè)平臺比不可少的一部分。雖然各家有各家的叫法,但都能滿足協(xié)程的基本要求—并發(fā)執(zhí)行和可大量創(chuàng)建。筆者對他們的實(shí)現(xiàn)方式總結(jié)了一下。

下面列舉一些已經(jīng)支持協(xié)程的常見的語言和平臺。

golang中的并發(fā)介紹

GoLang 和Scala作為最新的語言,一出生就有完善的基于協(xié)程并發(fā)功能。Erlang最為老資格的并發(fā)編程語言,返老還童。其他二線語言則幾乎全部在新的版本中加入了協(xié)程。

令人驚奇的是C/C++和Java這三個(gè)世界上最主流的平臺沒有在對協(xié)程提供語言級別的原生支持。他們都背負(fù)著厚重的歷史,無法改變,也無需改變。但他們還有其他的辦法使用協(xié)程。

Java平臺有很多方法實(shí)現(xiàn)協(xié)程:

· 修改虛擬機(jī):對JVM打補(bǔ)丁來實(shí)現(xiàn)協(xié)程,這樣的實(shí)現(xiàn)效果好,但是失去了跨平臺的好處

· 修改字節(jié)碼:在編譯完成后增強(qiáng)字節(jié)碼,或者使用新的JVM語言。稍稍增加了編譯的難度。

· 使用JNI:在Jar包中使用JNI,這樣易于使用,但是不能跨平臺。

· 使用線程模擬協(xié)程:使協(xié)程重量級,完全依賴JVM的線程實(shí)現(xiàn)。

其中修改字節(jié)碼的方式比較常見。因?yàn)檫@樣的實(shí)現(xiàn)辦法,可以平衡性能和移植性。最具代表性的JVM語言Scale就能很好的支持協(xié)程并發(fā)。流行的Java Actor模型類庫akka也是用修改字節(jié)碼的方式實(shí)現(xiàn)的協(xié)程。

對于C語言,協(xié)程和線程一樣??梢允褂酶鞣N各樣的系統(tǒng)調(diào)用來實(shí)現(xiàn)。協(xié)程作為一個(gè)比較高級的概念,實(shí)現(xiàn)方式實(shí)在太多,就不討論了。比較主流的實(shí)現(xiàn)有l(wèi)ibpcl, coro,lthread等等。

對于C++,有Boost實(shí)現(xiàn),還有一些其他開源庫。還有一門名為μC++語言,在C++基礎(chǔ)上提供了并發(fā)擴(kuò)展。

可見這種編程模型在眾多的語言平臺中已經(jīng)得到了廣泛的支持,不再小眾。如果想使用的話,隨時(shí)可以加到自己的工具箱中。

上述就是小編為大家分享的golang中的并發(fā)介紹了,如果您也有類似的疑惑,不妨參照上述方法進(jìn)行嘗試。如果想了解更多相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI