go并發(fā)之goroutine和channel厦幅,并發(fā)控制入門(mén)篇

并發(fā)的概念及其重要性

這段是簡(jiǎn)單科普沾鳄,大佬可以跳過(guò)

并發(fā):并發(fā)程序指同時(shí)進(jìn)行多個(gè)任務(wù)的程序。在操作系統(tǒng)中确憨,是指一個(gè)時(shí)間段中有幾個(gè)程序都處于已啟動(dòng)運(yùn)行到運(yùn)行完畢之間译荞,且這幾個(gè)程序都是在同一個(gè)處理機(jī)上運(yùn)行,但任一個(gè)時(shí)刻點(diǎn)上只有一個(gè)程序在處理機(jī)上運(yùn)行休弃。

----------本段引用內(nèi)容源自《GO語(yǔ)言高級(jí)編程》

在早期吞歼,CPU都是以單核的形式順序執(zhí)行機(jī)器指令。Go語(yǔ)言的祖先C語(yǔ)言正是這種順序編程語(yǔ)言的代表塔猾。順序編程語(yǔ)言中的順序是指:所有的指令都是以串行的方式執(zhí)行浆熔,在相同的時(shí)刻有且僅有一個(gè)CPU在順序執(zhí)行程序的指令。

隨著處理器技術(shù)的發(fā)展,單核時(shí)代以提升處理器頻率來(lái)提高運(yùn)行效率的方式遇到了瓶頸医增,目前各種主流的CPU頻率基本被鎖定在了3GHZ附近慎皱。單核CPU的發(fā)展的停滯,給多核CPU的發(fā)展帶來(lái)了機(jī)遇叶骨。相應(yīng)地茫多,編程語(yǔ)言也開(kāi)始逐步向并行化的方向發(fā)展。Go語(yǔ)言正是在多核和網(wǎng)絡(luò)化的時(shí)代背景下誕生的原生支持并發(fā)的編程語(yǔ)言忽刽。

在聊并發(fā)之前天揖,聊聊共享變量、線(xiàn)程跪帝、協(xié)程

  1. 如何在不同線(xiàn)程/協(xié)程 共享 變量/內(nèi)存今膊?

這里留給各位看官去自行查資料,即使我列出來(lái)也不如自己動(dòng)手去查記憶深刻伞剑!

不想查也可以等我下一篇文章斑唬,更加詳細(xì)解讀線(xiàn)程、進(jìn)程黎泣。

  1. 線(xiàn)程和協(xié)程概念恕刘?

線(xiàn)程:線(xiàn)程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。一個(gè)進(jìn)程可以包含多個(gè)線(xiàn)程抒倚,是進(jìn)程中的實(shí)際運(yùn)作單位褐着。

協(xié)程:又稱(chēng)微線(xiàn)程。協(xié)程是一種用戶(hù)態(tài)的輕量級(jí)線(xiàn)程托呕。協(xié)程擁有自己的寄存器上下文和棧含蓉。協(xié)程調(diào)度切換時(shí),將寄存器上下文和棧保存到其他地方项郊,在切回來(lái)的時(shí)候谴餐,恢復(fù)先前保存的寄存器上下文和棧。

  1. 為什么會(huì)誕生協(xié)程呆抑?

雖然多線(xiàn)程在前互聯(lián)網(wǎng)世代已經(jīng)足夠使用岂嗓,但是線(xiàn)程的局限性也比較明顯

  1. 線(xiàn)程數(shù)量有限,一般不會(huì)很多
  2. 線(xiàn)程占據(jù)的資源通常比我們需要的多得多鹊碍,造成浪費(fèi)

每個(gè)系統(tǒng)級(jí)線(xiàn)程開(kāi)辟都會(huì)占用空間厌殉,這個(gè)空間可能是MB級(jí)別,但是我們?nèi)绻褂玫木€(xiàn)程只需要傳遞KB級(jí)別數(shù)據(jù)侈咕,那么線(xiàn)程看起來(lái)就會(huì)比較浪費(fèi)公罕,但是又不可避免。而且線(xiàn)程之間的切換也會(huì)占用一些額外開(kāi)銷(xiāo)耀销。

為了解決上面的矛盾問(wèn)題楼眷,協(xié)程誕生了:更小的資源開(kāi)支,動(dòng)態(tài)調(diào)配資源,比線(xiàn)程更輕量罐柳。

協(xié)程的一些優(yōu)點(diǎn):

  1. 因?yàn)樽映绦蚯袚Q不是線(xiàn)程切換掌腰,而是由程序自身控制,因此张吉,沒(méi)有線(xiàn)程切換的開(kāi)銷(xiāo)齿梁,和多線(xiàn)程比,線(xiàn)程數(shù)量越多肮蛹,協(xié)程的性能優(yōu)勢(shì)就越明顯勺择。
  2. 不需要多線(xiàn)程的鎖機(jī)制,因?yàn)橹挥幸粋€(gè)線(xiàn)程伦忠,也不存在同時(shí)寫(xiě)變量沖突省核,在協(xié)程中控制共享資源不加鎖,只需要判斷狀態(tài)就好了昆码,所以執(zhí)行效率比多線(xiàn)程高很多气忠。

在golang中,goroutine的創(chuàng)建消耗非常小未桥,大約是KB級(jí)別笔刹。因此可以創(chuàng)建更多的協(xié)程芥备,尤其是數(shù)量越多相對(duì)線(xiàn)程優(yōu)勢(shì)更加明顯冬耿,而且goroutine可以動(dòng)態(tài)伸縮,棧溢出風(fēng)險(xiǎn)也比線(xiàn)程更低萌壳。

golang的并發(fā)亦镶,goroutine的使用

var name = "yiyiyinhe"

func changeName() {
    name = "change"
}

func sayHi() {
    fmt.println("hi, ", name)
    go changeName() // 協(xié)程
}

簡(jiǎn)單的協(xié)程就創(chuàng)建了,那么打印出來(lái)的結(jié)果可能是hi, yiyiyinhe也可能是hi, change袱瓮。

如果想對(duì)某一代碼塊執(zhí)行協(xié)程而不是某個(gè)方法缤骨,則使用下面方式

var name = "yiyiyinhe"

func sayHi() {
    fmt.println("hi, ", name)
    go func() { // 匿名函數(shù)執(zhí)行協(xié)程
        name = "change"
    }
}

channel

golang對(duì)共享變量的口號(hào)

Do not communicate by sharing memory; instead, share memory by communicating.

不要通過(guò)共享內(nèi)存來(lái)通信,而應(yīng)通過(guò)通信來(lái)共享內(nèi)存尺借。

那么在協(xié)程中也需要進(jìn)行通信绊起,而golang使用的goroutine之間通信和同步的主要方法是channel。

什么是channel呢燎斩?

A channel is a communic ation mechanism that lets one goroutine send values to another goroutine. Each channel is a conduit for values of a particular type, called the channel’s element type.

channel是一種通信機(jī)制虱歪,它讓一個(gè)goroutine向另一個(gè)goroutine發(fā)送值。每個(gè)通道都是特定類(lèi)型(通道元素類(lèi)型)值的管道栅表。

簡(jiǎn)單來(lái)理解就是笋鄙,channel是用于在goroutine中進(jìn)行通信的管道,而且管道是有特定類(lèi)型的怪瓶。

創(chuàng)建的channel分為有緩存和無(wú)緩存兩種萧落,區(qū)別就是創(chuàng)建的時(shí)候是否分配大小

  • 無(wú)緩存channel

    • var ch1 = make(chan int),未分配大小
    • var ch2 = make(chan int, 0),分配大小為0也等同給于未分配大小
  • 有緩存channel

    • var :ch3 = make(int, 3)找岖,分配大小為3的有緩存channel

無(wú)緩存channel中陨倡,channel的發(fā)送操作總是在接收之前發(fā)生;簡(jiǎn)單理解就是宣增,無(wú)緩存channel是一個(gè)管道必須從頭flag<-true發(fā)送到尾部<-flag玫膀,而且尾部發(fā)生的時(shí)間一定是在頭部發(fā)送之后。

  • 為什么chennel可以這樣呢爹脾?

    因?yàn)閏hannel有阻塞作用帖旨,必須接收了才能繼續(xù)下去。

channel

有緩存channel則不具備上述的特性灵妨,因?yàn)閷?duì)于帶緩沖的Channel解阅,對(duì)于Channel的第 K 個(gè)接收完成操作發(fā)生在第 K+C 個(gè)發(fā)送操作完成之前,其中 C 是Channel的緩存大小泌霍。 如果將 C 設(shè)置為0自然就對(duì)應(yīng)無(wú)緩存的Channel货抄,也即使第K個(gè)接收完成在第K個(gè)發(fā)送完成之前。因?yàn)闊o(wú)緩存的Channel只能同步發(fā)1個(gè)朱转,也就簡(jiǎn)化為前面無(wú)緩存Channel的規(guī)則:對(duì)于從無(wú)緩沖Channel進(jìn)行的接收蟹地,發(fā)生在對(duì)該Channel進(jìn)行的發(fā)送完成之前。

還是上面的例子藤为,使用channel來(lái)演示一下

var name = "yiyi"
var flag = make(chan bool) // 創(chuàng)建了bool類(lèi)型的channel

func changeName() {
    name = "change"
    flag <- true  // 發(fā)送
}

func sayHi() {
    go changeName() // 協(xié)程
    <-flag // 接收
    fmt.println("hi, ", name)
}

那么這個(gè)時(shí)候打印出來(lái)的就是一個(gè)固定的順序怪与,由于<-flag接收總是在發(fā)送之后執(zhí)行,因此當(dāng)flag <- true執(zhí)行完之前name = "change"已經(jīng)執(zhí)行缅疟,打印結(jié)果一定是:hi, change

上面代碼等同于下圖所示

image

看完你可以收獲什么分别?

  1. 簡(jiǎn)單了解并發(fā),了解多線(xiàn)程簡(jiǎn)單的發(fā)展來(lái)歷
  2. 簡(jiǎn)單了解線(xiàn)程存淫,協(xié)程
  3. 為什么協(xié)程會(huì)誕生耘斩?
  4. goroutine的兩種使用方式
  5. channel是什么?channel的兩種分類(lèi)桅咆;
  6. channel在goroutine中有什么作用括授?

寫(xiě)在最后

由于我剛開(kāi)始寫(xiě)技術(shù)文章,很多東西不知道怎么寫(xiě)才能讓大家都看懂岩饼,就像寫(xiě)線(xiàn)程協(xié)程的時(shí)候不知道要不要解釋共享變量或者共享內(nèi)存是什么荚虚,也不知道大家能不能知道多線(xiàn)程模式下線(xiàn)程之間通信有哪些方式,感覺(jué)都想寫(xiě)但是又覺(jué)得大家看文章標(biāo)題應(yīng)該是了解一些東西的忌愚,如果都寫(xiě)篇幅太長(zhǎng)曲管,不寫(xiě)又看不懂;就覺(jué)得比較矛盾吧硕糊,也希望大家能夠給我提一些意見(jiàn)建議院水!

作者還在慢慢努力腊徙,盡量把文章寫(xiě)的通俗易懂,排版準(zhǔn)確檬某,抓住重點(diǎn)撬腾,把最好的內(nèi)容展現(xiàn)給大家。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恢恼,一起剝皮案震驚了整個(gè)濱河市民傻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌场斑,老刑警劉巖漓踢,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異漏隐,居然都是意外死亡喧半,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)青责,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挺据,“玉大人,你說(shuō)我怎么就攤上這事脖隶”饽停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵产阱,是天一觀(guān)的道長(zhǎng)婉称。 經(jīng)常有香客問(wèn)我,道長(zhǎng)心墅,這世上最難降的妖魔是什么酿矢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任榨乎,我火速辦了婚禮怎燥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜜暑。我一直安慰自己铐姚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布肛捍。 她就那樣靜靜地躺著隐绵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拙毫。 梳的紋絲不亂的頭發(fā)上依许,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音缀蹄,去河邊找鬼峭跳。 笑死膘婶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛀醉。 我是一名探鬼主播悬襟,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拯刁!你這毒婦竟也來(lái)了脊岳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤垛玻,失蹤者是張志新(化名)和其女友劉穎割捅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體帚桩,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棺牧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朗儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颊乘。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖醉锄,靈堂內(nèi)的尸體忽然破棺而出乏悄,到底是詐尸還是另有隱情,我是刑警寧澤恳不,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布檩小,位于F島的核電站,受9級(jí)特大地震影響烟勋,放射性物質(zhì)發(fā)生泄漏规求。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一卵惦、第九天 我趴在偏房一處隱蔽的房頂上張望阻肿。 院中可真熱鬧,春花似錦沮尿、人聲如沸丛塌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赴邻。三九已至,卻和暖如春啡捶,著一層夾襖步出監(jiān)牢的瞬間姥敛,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工瞎暑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彤敛,地道東北人忿偷。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像臊泌,于是被迫代替她去往敵國(guó)和親鲤桥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容