Go的Goroutine的使用

并發(fā) concurrency

  • Goroutine 通過(guò)通信來(lái)共享內(nèi)存,而不是通過(guò)共享內(nèi)存來(lái)通信
  1. Channel是Goroutine的溝通橋梁,引用類型,大都是阻塞同步的
  2. make創(chuàng)建,close關(guān)閉
  3. for range迭代操作channel,可以設(shè)置單向或者雙向管道,緩存大小,為填滿之前不會(huì)堵塞
  • Select
  1. 可以處理一個(gè)或者多個(gè)channel的發(fā)送和接收
  2. 同時(shí)有多個(gè)可以用的chnnel隨機(jī)順序處理
  3. 可設(shè)置空的select阻塞main函數(shù),可設(shè)置超時(shí)
  • 單向管道 chan<-int只發(fā)送同道,<-chan int供常,只接受通道
func initV(out chan<- int) {
    for i := 0; i < 1000; i++ {
        out <- i
    }
    close(out)
}

func squar(in <-chan int, out chan<- int) {
    for i := range in {
        out <- i * i;
    }
    close(out)
}

func print(in <-chan int) {
    for i := range in {
        fmt.Println("value is:", i)
    }
}

    x:=make(chan int)
    y:=make(chan int)
    go initV(x)
    go squar(x,y)
     print(y)

chan異步處理循環(huán)打印

func ChanRange(index int,c chan bool) {
    a := 0
    for i := 0; i < 100000000; i++ {
        a += i
    }
    fm.Println("a value is:",index, a)
    c<-true//設(shè)置chan值
}

func goChan() {//達(dá)到異步執(zhí)行
    runtime.GOMAXPROCS(1)/設(shè)置cpu最大可用核數(shù)
    c := make(chan bool,10)//設(shè)置緩存大小,有緩存的時(shí)候是異步的,無(wú)緩存是同步堵塞
    for i := 0; i < 10; i++ {
        go my.ChanRange(i,c)//開啟一個(gè)新的goroutine執(zhí)行
    }
    for i:=0;i<10;i++{
        <-c//取出chan值
    }

}

sync異步循環(huán)打印

func SyncRange(index int,wg *sync.WaitGroup) {
    a := 0
    for i := 0; i < 100000000; i++ {
        a += i
    }
    fm.Println("a value is:",index, a)
    wg.Done()//執(zhí)行完畢一個(gè),線程池就會(huì)減少一個(gè)線程
}

func goSync() {//達(dá)到異步執(zhí)行
    //runtime.GOMAXPROCS(runtime.NumCPU())/設(shè)置cpu最大可用核數(shù)
    wg:=sync.WaitGroup{}
    wg.Add(10)
    for i := 0; i < 10; i++ {
        go my.SyncRange(i,&wg)
    }
    wg.Wait()

}

并發(fā)不是并行,==老的版本默認(rèn)==,Go所有的goroutines只能在一個(gè)線程里跑,也就是說(shuō),設(shè)置核數(shù)為1地,goChan方法不是并行的律杠,是并發(fā)的块差,==新版本默認(rèn)==把runtime.GOMAXPROCS(runtime.NumCPU())設(shè)置最大的,那么他就是并行的

  • 兩個(gè)隊(duì)列,一個(gè)Coffee機(jī)器燎潮,那是并發(fā)
  • 兩個(gè)隊(duì)列喻鳄,兩個(gè)Coffee機(jī)器,那是并行
package main

import (
    "fmt"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        fmt.Println(s)
    }
}

func main() {
    go say("world") //開一個(gè)新的Goroutines執(zhí)行
    for {
    }
}

這里Go仍然在使用單核确封,for死循環(huán)占據(jù)了單核CPU所有的資源除呵,而main線和say兩個(gè)goroutine都在一個(gè)線程里面,所以say沒(méi)有機(jī)會(huì)執(zhí)行

  • 允許Go使用多核(runtime.GOMAXPROCS)

  • 手動(dòng)顯式調(diào)動(dòng)runtime包(runtime包是goroutine的調(diào)度器),

    • Gosched 讓出cpu
    • NumCPU 返回當(dāng)前系統(tǒng)的CPU核數(shù)量
    • GOMAXPROCS 設(shè)置最大的可同時(shí)使用的CPU核數(shù)
    • Goexit 退出當(dāng)前goroutine(但是defer語(yǔ)句會(huì)照常執(zhí)行)
func loop() {
    for i := 0; i < 10; i++ {
        runtime.Gosched() // 顯式地讓出CPU時(shí)間給其他goroutine
        fmt.Printf("%d ", i)
    }
    quit <- 0
}


func main() {

    go loop()
    go loop()

    for i := 0; i < 2; i++ {
        <- quit
    }
}

- 上面代碼這種主動(dòng)讓出CPU時(shí)間的方式仍然是在單核里跑爪喘。但手工地切換goroutine導(dǎo)致了看上去的“并行”颜曾,stackoverflow的 解釋:https://stackoverflow.com/questions/13107958/what-exactly-does-runtime-gosched-do

當(dāng)一個(gè)goroutine發(fā)生阻塞,Go會(huì)自動(dòng)地把與該goroutine處于同一系統(tǒng)線程的其他goroutines轉(zhuǎn)移到另一個(gè)系統(tǒng)線程上去秉剑,以使這些goroutines不阻塞,也就是說(shuō),goroutine不阻塞不放開CPU

package main

import (
    "fmt"
    "runtime"
)

var quit chan int = make(chan int)

func loop(id int) { // id: 該goroutine的標(biāo)號(hào)
    for i := 0; i < 10; i++ { //打印10次該goroutine的標(biāo)號(hào)
        fmt.Printf("%d ", id)
    }
    quit <- 0
}

func main() {
    runtime.GOMAXPROCS(2) // 最多同時(shí)使用2個(gè)核

    for i := 0; i < 3; i++ { //開三個(gè)goroutine
        go loop(i)
    }

    for i := 0; i < 3; i++ {
        <- quit
    }
}

select的使用

  • 多chan 處理
func TwoMoreChan() {
    c1, c2 := make(chan bool), make(chan int)
    o := make(chan bool)

    go func() {
        for {
            select {
            case v, ok := <-c1:
                if !ok {
                    o <- true
                    break
                }
                fm.Println("c1 value is:", v)
            case v, ok := <-c2:
                if !ok {
                    o <- true
                    break
                }
                fm.Println("c2 value is:", v)
            }
        }
    }()

    c1 <- false
    c2 <- 0
    c1 <- true
    c2 <- 2

    close(c1) 
}
  • 設(shè)置超時(shí)處理
func SelectTime() {
    c := make(chan bool)
    select {
    case v := <-c:
        fm.Println("c value is:", v)
    case <-time.After(3 * time.Second):
        fm.Println("time out")
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末泛豪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子秃症,更是在濱河造成了極大的恐慌候址,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件种柑,死亡現(xiàn)場(chǎng)離奇詭異岗仑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)聚请,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門荠雕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人驶赏,你說(shuō)我怎么就攤上這事炸卑。” “怎么了煤傍?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵盖文,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蚯姆,道長(zhǎng)五续,這世上最難降的妖魔是什么洒敏? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮疙驾,結(jié)果婚禮上凶伙,老公的妹妹穿的比我還像新娘。我一直安慰自己它碎,他們只是感情好函荣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扳肛,像睡著了一般傻挂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敞峭,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天踊谋,我揣著相機(jī)與錄音蝉仇,去河邊找鬼旋讹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛轿衔,可吹牛的內(nèi)容都是我干的沉迹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼害驹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鞭呕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起宛官,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤葫松,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后底洗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腋么,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年亥揖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珊擂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡费变,死狀恐怖摧扇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挚歧,我是刑警寧澤扛稽,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站滑负,受9級(jí)特大地震影響在张,放射性物質(zhì)發(fā)生泄漏锡搜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一瞧掺、第九天 我趴在偏房一處隱蔽的房頂上張望耕餐。 院中可真熱鬧,春花似錦辟狈、人聲如沸肠缔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)明未。三九已至,卻和暖如春壹蔓,著一層夾襖步出監(jiān)牢的瞬間趟妥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工佣蓉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留披摄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓勇凭,卻偏偏與公主長(zhǎng)得像疚膊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子虾标,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354