新聞中心
通過(guò)上一節(jié)《 Go語(yǔ)言goroutine》的學(xué)習(xí),關(guān)鍵字 go 的引入使得在Go語(yǔ)言中并發(fā)編程變得簡(jiǎn)單而優(yōu)雅,但我們同時(shí)也應(yīng)該意識(shí)到并發(fā)編程的原生復(fù)雜性,并時(shí)刻對(duì)并發(fā)中容易出現(xiàn)的問(wèn)題保持警惕。

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于做網(wǎng)站、網(wǎng)站設(shè)計(jì)、江寧網(wǎng)絡(luò)推廣、微信平臺(tái)小程序開(kāi)發(fā)、江寧網(wǎng)絡(luò)營(yíng)銷、江寧企業(yè)策劃、江寧品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供江寧建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:www.cdcxhl.com
事實(shí)上,不管是什么平臺(tái),什么編程語(yǔ)言,不管在哪,并發(fā)都是一個(gè)大話題。并發(fā)編程的難度在于協(xié)調(diào),而協(xié)調(diào)就要通過(guò)交流,從這個(gè)角度看來(lái),并發(fā)單元間的通信是最大的問(wèn)題。
在工程上,有兩種最常見(jiàn)的并發(fā)通信模型:共享數(shù)據(jù)和消息。
共享數(shù)據(jù)是指多個(gè)并發(fā)單元分別保持對(duì)同一個(gè)數(shù)據(jù)的引用,實(shí)現(xiàn)對(duì)該數(shù)據(jù)的共享。被共享的數(shù)據(jù)可能有多種形式,比如內(nèi)存數(shù)據(jù)塊、磁盤文件、網(wǎng)絡(luò)數(shù)據(jù)等。在實(shí)際工程應(yīng)用中最常見(jiàn)的無(wú)疑是內(nèi)存了,也就是常說(shuō)的共享內(nèi)存。
先看看我們?cè)贑語(yǔ)言中通常是怎么處理線程間數(shù)據(jù)共享的,代碼如下所示。
#include#include #include void *count(); pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; int counter = 0; int main() { int rc1, rc2; pthread_t thread1, thread2; /* 創(chuàng)建線程,每個(gè)線程獨(dú)立執(zhí)行函數(shù)functionC */ if((rc1 = pthread_create(&thread1, NULL, &count, NULL))) { printf("Thread creation failed: %d\n", rc1); } if((rc2 = pthread_create(&thread2, NULL, &count, NULL))) { printf("Thread creation failed: %d\n", rc2); } /* 等待所有線程執(zhí)行完畢 */ pthread_join( thread1, NULL); pthread_join( thread2, NULL); exit(0); } void *count() { pthread_mutex_lock( &mutex1 ); counter++; printf("Counter value: %d\n",counter); pthread_mutex_unlock( &mutex1 ); }
現(xiàn)在我們嘗試將這段C語(yǔ)言代碼直接翻譯為Go語(yǔ)言代碼,代碼如下所示。
package main
import (
"fmt"
"runtime"
"sync"
)
var counter int = 0
func Count(lock *sync.Mutex) {
lock.Lock()
counter++
fmt.Println(counter)
lock.Unlock()
}
func main() {
lock := &sync.Mutex{}
for i := 0; i < 10; i++ {
go Count(lock)
}
for {
lock.Lock()
c := counter
lock.Unlock()
runtime.Gosched()
if c >= 10 {
break
}
}
}在上面的例子中,我們?cè)?10 個(gè) goroutine 中共享了變量 counter。每個(gè) goroutine 執(zhí)行完成后,會(huì)將 counter 的值加 1。因?yàn)?10 個(gè) goroutine 是并發(fā)執(zhí)行的,所以我們還引入了鎖,也就是代碼中的 lock 變量。每次對(duì) n 的操作,都要先將鎖鎖住,操作完成后,再將鎖打開(kāi)。
在 main 函數(shù)中,使用 for 循環(huán)來(lái)不斷檢查 counter 的值(同樣需要加鎖)。當(dāng)其值達(dá)到 10 時(shí),說(shuō)明所有 goroutine 都執(zhí)行完畢了,這時(shí)主函數(shù)返回,程序退出。
事情好像開(kāi)始變得糟糕了。實(shí)現(xiàn)一個(gè)如此簡(jiǎn)單的功能,卻寫出如此臃腫而且難以理解的代碼。想象一下,在一個(gè)大的系統(tǒng)中具有無(wú)數(shù)的鎖、無(wú)數(shù)的共享變量、無(wú)數(shù)的業(yè)務(wù)邏輯與錯(cuò)誤處理分支,那將是一場(chǎng)噩夢(mèng)。這噩夢(mèng)就是眾多 C/ C++ 開(kāi)發(fā)者正在經(jīng)歷的,其實(shí) Java 和 C# 開(kāi)發(fā)者也好不到哪里去。
Go語(yǔ)言既然以并發(fā)編程作為語(yǔ)言的最核心優(yōu)勢(shì),當(dāng)然不至于將這樣的問(wèn)題用這么無(wú)奈的方式來(lái)解決。Go語(yǔ)言提供的是另一種通信模型,即以消息機(jī)制而非共享內(nèi)存作為通信方式。
消息機(jī)制認(rèn)為每個(gè)并發(fā)單元是自包含的、獨(dú)立的個(gè)體,并且都有自己的變量,但在不同并發(fā)單元間這些變量不共享。每個(gè)并發(fā)單元的輸入和輸出只有一種,那就是消息。這有點(diǎn)類似于進(jìn)程的概念,每個(gè)進(jìn)程不會(huì)被其他進(jìn)程打擾,它只做好自己的工作就可以了。不同進(jìn)程間靠消息來(lái)通信,它們不會(huì)共享內(nèi)存。
Go語(yǔ)言提供的消息通信機(jī)制被稱為 channel,關(guān)于 channel 的介紹將在后續(xù)的學(xué)習(xí)中為大家講解。
當(dāng)前題目:創(chuàng)新互聯(lián)GO教程:Go語(yǔ)言并發(fā)通信
文章出自:http://m.5511xx.com/article/dhcjcoj.html


咨詢
建站咨詢
