Golang併發程式設計程式通訊channel瞭解及簡單使用

OldBoy~發表於2018-09-16

概念及作用

channel是一個資料型別,用於實現同步,用於兩個協程之間交換資料。goroutine奉行通過通訊來共享記憶體,而不是共享記憶體來通訊。
引用型別channel是CSP模式的具體實現,用於多個goroutine通訊。其內部實現了同步,確保併發安全。

建立及使用
每個channel在建立的時候必須指定一個型別,指定的型別是任意的。

ch := make(chan int)   //使用內建的make函式,可以建立一個channel型別
// 傳送資料到channel
ch <- 1
// 從channel接受資料
x := <- ch

案例舉例(一)

①建立channel前

package main

import (
    "fmt"
    "time"
)

//定義一個印表機,引數為字串,按每個字元列印
//印表機屬於公共資源
func Printer(str string) {
    for _, data := range str {
        fmt.Printf("%c", data)
        time.Sleep(time.Second)
    }
    fmt.Printf("\n")
}

func person1() {
    Printer("hello")
}

func person2() {
    Printer("world")
}

func main() {
    //新建2個協程,代表2個人,2個人同時使用印表機
    go person1()
    go person2()

    //特地不讓主協程結束,死迴圈
    for {

    }
}
//結果
hwoerllldo   //交叉執行

②建立channel後(注意channel變數和呼叫的先後順序)

package main

import (
    "fmt"
    "time"
)

//全域性變數,建立一個channel
var ch = make(chan int)

//定義一個印表機,引數為字串,按每個字元列印
//印表機屬於公共資源
func Printer(str string) {
    for _, data := range str {
        fmt.Printf("%c", data)
        time.Sleep(time.Second)
    }
    fmt.Printf("\n")
}

//person1執行完後,才能到person2執行
func person1() {
    Printer("hello")
    ch <- 666 //給管道寫資料,傳送
}

func person2() {
    <-ch //從管道取資料,接收,如果通道沒有資料他就會阻塞
    Printer("world")
}

func main() {
    //新建2個協程,代表2個人,2個人同時使用印表機
    go person1()
    go person2()

    //特地不讓主協程結束,死迴圈
    for {

    }
}
hello
world

案例舉例(二)

package main

import (
    "fmt"
)

func main() {
    ch := make(chan string)
    go func() {
        fmt.Println("aaaaaaaaaa")
        str := <-ch // 在執行到這一步的時候main goroutine才會停止阻塞
        fmt.Println("取出channel的資料" + str)
    }()
    fmt.Println("bbbbbbbbbb")
    ch <- "hello" // 如果沒有其他goroutine來取走這個資料,main goroutine掛起,直到其它gorouteine把資料拿走(這裡會暫時阻塞)
    fmt.Println("cccccccccc")
}
bbbbbbbbbb
aaaaaaaaaa
取出channel的資料hello
cccccccccc

 

相關文章