Go的並發沒有它,就像iphone沒有網路一樣

來源:互聯網
上載者:User

Go的並發沒有它,就像iphone沒有網路一樣

簡介

Golang的並發屬性是該語言的一個大殺器,說到並發就不能不提Channel,你可以把它看成一個管道,通過它並發核心單元就可以發送或者接收資料進行通訊。這篇文章來深入瞭解一下 channel。

channel 的設計是基於 CSP 模型的。CSP 是 Communicating Sequential Process 的簡稱,中文可以叫做通訊順序進程,是一種並發編程模型,由 Tony Hoare 於 1977 年提出。簡單來說,CSP 模型由並發執行的實體(線程或者進程)所組成,實體之間通過發送訊息進行通訊,這裡發送訊息時使用的就是通道,或者叫 channel。CSP 模型的關鍵是關注 channel,而不關注發送訊息的實體。Go 語言實現了 CSP 部分理論,goroutine 對應 CSP 中並發執行的實體,channel 也就對應著 CSP 中的 channel。

建立Channel

  • Go中的Channel使用chan作為關鍵字。

  • 無緩衝chan情況下,發送和接收會一直阻塞著,直到另一方準備好。這種方式可以用來在gororutine中進行同步,- 而需要使用鎖或者條件變數。

  • 有緩衝chan,可以盡量避免阻塞,提高應用的效能,典型的以時間換空間。

aChan := make(chan int)  // 建立無緩衝chanbChan := make(chan int, N) // 建立緩衝為N的chan</pre>

賦值和取值

從以下代碼中看不出它的巨大作用,很正常,那是因為他們兩條語句通常不在一起,例如:協程A發送資料,協程B接收資料

mchan <- value  // 發送值v到Channel ch中value := <-mchan // 從Channel ch中接收資料,並將資料賦值給v

Select

Selsect是擷取Channel中資料的最常用方式。

select 一定程度上可以類比於 linux 中的 IO 多工中的 select。後者相當於提供了對多個 IO 事件的統一管理,而 Golang 中的 select 相當於提供了對多個 channel 的統一管理。當然這隻是 select 在 channel 上的一種使用方法。

func main(){    ch1 := make(chan int, 1)    ch2 := make(chan int, 1)    select {        case e1 := <-ch1:        //如果ch1通道成功讀取資料,則執行該case處理語句            fmt.Printf("1th case is selected. e1=%v",e1)        case e2 := <-ch2:        //如果ch2通道成功讀取資料,則執行該case處理語句            fmt.Printf("2th case is selected. e2=%v",e2)        default:        //如果上面case都沒有成功,則進入default處理流程            fmt.Println("default!.")    }}

for...range

for …… range語句可以處理Channel。

    go func() {        time.Sleep(1 * time.Hour)    }()    c := make(chan int)    go func() {        for i := 0; i < 10; i = i + 1 {            c <- i        }        close(c)    }()    for i := range c {        fmt.Println(i)    }    fmt.Println("Finished")

timeout

Select很重要的一個應用就是逾時處理。 因為上面提供的demo,select語句就會一直阻塞著。這時候我們可能就需要一個逾時操作,用來處理逾時的情況。下面這個例子我們會在2秒後往channel c1中發送一個資料,但是Select設定為1秒逾時,因此我們會列印出timeout 1,而不是result 1。

    c1 := make(chan string, 1)    go func() {        time.Sleep(time.Second * 2)        c1 <- "result 1"    }()    select {    case res := <-c1:        fmt.Println(res)    case <-time.After(time.Second * 1):        fmt.Println("timeout 1")    }

close

Go內建的close方法就可以用來關閉channel。但如果channel 已經被關閉,繼續往它發送資料會導致panic: send on closed channel:

close(mChan)

推薦閱讀
有,總比沒有要好:Go依賴管理工具dep
工欲善其事,必先利其器 (Go開發工具)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.