并發(fā)編程

goroutine

它是go并發(fā)設(shè)計(jì)的核心荞驴。
goroutine就是協(xié)程琐谤,它比線程更小,十幾個(gè)goroutine在底層可能就是五六個(gè)線程魄懂。
go語言內(nèi)部實(shí)現(xiàn)了goroutine的內(nèi)存共享囤屹,執(zhí)行g(shù)oroutine只需極少的棧內(nèi)存(大概是4~5KB)。
main函數(shù)是主協(xié)程逢渔,如果主協(xié)程退出其他任務(wù)也不會(huì)執(zhí)行肋坚,程序直接退出。

runtime包

runtime.Gosched()

runtime.Gosched()用于讓出CPU時(shí)間片肃廓,調(diào)度器會(huì)重新進(jìn)行任務(wù)調(diào)度智厌,但是有可能還是分配到該任務(wù)

 package main

  import (
     "fmt"
     "runtime"
  )

  func main() {
     //匿名子協(xié)程
     go func(s string) {
        for i := 0; i < 2; i++ {
           fmt.Println(s)
        }
     }("world")
     //主協(xié)程
     for i := 0; i < 2; i++ {
        runtime.Gosched()
        fmt.Println("hello")
     }
  }
runtime.Goexit()

立即終止當(dāng)前協(xié)程,但是會(huì)保證已經(jīng)注冊(cè)的defer延遲調(diào)用都被執(zhí)行盲赊。

  package main

  import (
     "fmt"
     "time"
     "runtime"
  )

  func main() {
     //匿名子協(xié)程
     go func() {
        defer fmt.Println("A.defer")
        //匿名函數(shù)
        func() {
           defer fmt.Println("B.defer")
           //此時(shí)只有defer執(zhí)行
           runtime.Goexit()
           fmt.Println("B")
        }()
        fmt.Println("A")
     }()
     for {
        time.Sleep(time.Second)
     }
  }

該程序執(zhí)行只會(huì)輸出

B.defer
A.defer
runtime.GOMAXPROCS()

設(shè)置并發(fā)執(zhí)行的CPU個(gè)數(shù)并返回之前的值

  package main

  import (
     "runtime"
     "fmt"
  )

  func main() {
     n := runtime.GOMAXPROCS(3)
     fmt.Println("n=%d\n",n)
     //循環(huán)執(zhí)行2個(gè)
     for{
        go fmt.Print(0)
        fmt.Print(1)
     }
  }
runtime. NumCPU()

返回系統(tǒng)的CPU數(shù)量

runtime. NumGoroutine()

返回正在執(zhí)行和排隊(duì)的所有任務(wù)總數(shù)

runtime.GOOS

返回操作系統(tǒng)

channel

創(chuàng)建

channel可以用內(nèi)置make()函數(shù)創(chuàng)建
make(chan 類型) //無緩沖的通道铣鹏,阻塞
make(chan 類型, 容量) //有緩沖的通道,非阻塞

傳輸數(shù)據(jù)
  channel <- value   //發(fā)送value到channel
  <-channel          //接收通道數(shù)據(jù)哀蘑,并丟棄
  x := <-channel    //通道取值并賦給x
  x, ok := <-channel //ok是檢查通道是否關(guān)閉或者是否為空
遍歷
                for foundOre := range c {
            time.Sleep(2 * time.Second)
            fmt.Println("Miner: Received " + strconv.Itoa(foundOre) + " from finder")
        }

遍歷會(huì)阻塞直到有新數(shù)據(jù)發(fā)送到chanel诚卸,并且在遍歷成功后會(huì)繼續(xù)遍歷

關(guān)閉
close(c)

select

go語言提供了select關(guān)鍵字,可以監(jiān)聽channel上的數(shù)據(jù)流動(dòng)
語法與switch類似绘迁,區(qū)別是select要求每個(gè)case語句里必須是一個(gè)IO操作

  select {
  case <-chan1:
     // 如果chan1成功讀到數(shù)據(jù)合溺,則進(jìn)行該case處理語句
  case chan2 <- 1:
     // 如果成功向chan2寫入數(shù)據(jù),則進(jìn)行該case處理語句
  default:
     // 如果上面都沒有成功缀台,則進(jìn)入default處理流程,如果沒有default流程則select會(huì)阻塞直到有一個(gè)case成功
  }

sync包

Sync包同步提供基本的同步原語棠赛。
golang 并不推薦這個(gè)包中的大多數(shù)并發(fā)控制方法,但還是提供了相關(guān)方法膛腐,主要原因是golang中提倡以共享內(nèi)存的方式來通信睛约。

sync.Mutex

互斥鎖

var l sync.Mutex
l.Lock()
l.Unlock
sync.RWMutex

讀寫鎖
同時(shí)只能有一個(gè) goroutine 能夠獲得寫鎖定。
同時(shí)可以有任意多個(gè) gorouinte 獲得讀鎖定哲身。
同時(shí)只能存在寫鎖定或讀鎖定(讀和寫互斥)辩涝。

var l sync.RWMutex
l. RLock() // 加讀鎖
l. RUnlock() //加寫鎖
l. Lock()//加寫鎖
l. Unlock()//解寫鎖
sync. WaitGroup

WaitGroup可以用來等待一組goroutine結(jié)束

func (wg *WaitGroup) Add(delta int)//增加delta個(gè),注意勘天,wg.Add() 方法一定要在 goroutine 開始前執(zhí)行
func (wg *WaitGroup) Done() //計(jì)數(shù)-1
func (wg *WaitGroup) Wait() //等待結(jié)束
sync.Cond

條件變量

var locker = new(sync.Mutex)
var cond = sync.NewCond(locker)
cond. Broadcast() // 喚醒所有掛起的goroutine
cond.Signal() //喚醒1個(gè)goroutine
cond.Wait() //必須要獲取鎖才能調(diào)用怔揩,Wait方法在調(diào)用時(shí)會(huì)釋放底層鎖Locker棍丐,并且將當(dāng)前goroutine掛起,直到另一個(gè)goroutine執(zhí)行Signal或者Broadcase沧踏,該goroutine才有機(jī)會(huì)重新喚醒歌逢,并嘗試獲取Locker,完成后續(xù)邏輯
sync.Once

保證只執(zhí)行一次

    var once sync.Once
    onceBody := func() {
        fmt.Println("Only once")
    }
    done := make(chan bool)
    for i := 0; i < 10; i++ {
        go func() {
            once.Do(onceBody)
            done <- true
        }()
    }
    for i := 0; i < 10; i++ {
        <-done
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翘狱,一起剝皮案震驚了整個(gè)濱河市秘案,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌潦匈,老刑警劉巖阱高,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異茬缩,居然都是意外死亡赤惊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門凰锡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來未舟,“玉大人,你說我怎么就攤上這事掂为≡0颍” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵勇哗,是天一觀的道長(zhǎng)昼扛。 經(jīng)常有香客問我,道長(zhǎng)欲诺,這世上最難降的妖魔是什么抄谐? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮扰法,結(jié)果婚禮上蛹含,老公的妹妹穿的比我還像新娘。我一直安慰自己迹恐,他們只是感情好挣惰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著殴边,像睡著了一般。 火紅的嫁衣襯著肌膚如雪珍语。 梳的紋絲不亂的頭發(fā)上锤岸,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音板乙,去河邊找鬼是偷。 笑死拳氢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛋铆。 我是一名探鬼主播馋评,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼刺啦!你這毒婦竟也來了留特?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤玛瘸,失蹤者是張志新(化名)和其女友劉穎蜕青,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糊渊,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡右核,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渺绒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贺喝。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宗兼,靈堂內(nèi)的尸體忽然破棺而出搜变,到底是詐尸還是另有隱情,我是刑警寧澤针炉,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布挠他,位于F島的核電站,受9級(jí)特大地震影響篡帕,放射性物質(zhì)發(fā)生泄漏殖侵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一镰烧、第九天 我趴在偏房一處隱蔽的房頂上張望拢军。 院中可真熱鬧,春花似錦怔鳖、人聲如沸茉唉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽度陆。三九已至,卻和暖如春献幔,著一層夾襖步出監(jiān)牢的瞬間懂傀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工蜡感, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蹬蚁,地道東北人恃泪。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像犀斋,于是被迫代替她去往敵國(guó)和親贝乎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353