go14--併發concurrency,Goroutine ,channel

package main

/**

併發concurrency

不少人都是衝着 Go 大肆宣揚的高併發而忍不住躍躍欲試,但其實從
源碼的解析來看,goroutine 只是由官方實現的超級「線程池」而已。
不過話說回來,每一個實例 4-5KB 的棧內存佔用和因爲實現機制而大幅
減小的建立和銷燬開銷,是製造 Go 號稱的高併發的根本緣由。另外,
goroutine 的簡單易用,也在語言層面上給予了開發者巨大的便利。

併發不是並行:
併發切換時間片,單核是沒有並行的,只有一個線程,在並行則是直接利用
多核實現多線程的運行,多核是並行,有多個線程,但 Go 能夠設置使用核數,以發揮多核計算機
的能力。

高併發:由於建立銷燬的很快,每個佔內存很小,
Goroutine 奉行經過通訊來共享內存,而不是共享內存來通訊。

*/
import (
    "fmt"
    "runtime"
    "time"
)

func main1() {
    go GO()                     //這就是一個Goroutine,運行了一個Goroutine,
    time.Sleep(2 * time.Second) //暫停2秒鐘,不暫停是不會輸出的GOGOGO的,
}

func GO() {
    fmt.Println("GOGOGO")
}

func main2() {
    c := make(chan bool) //建立一個channel
    go func() {          //go後面接一個匿名函數
        fmt.Println("GGGGGOOOOOO")
        c <- true //channel中存入true或false隨便,
    }()
    <-c //從channel中取出來,go啓動一個Goroutine以後main函數就執行到<-c而且阻塞了,由於他在等着從
    //channel中取出東西來,只有c <- true執行了,放入東西到channel了,main就能夠取出東西來了,
    //通知main函數,他那裏執行完畢了,main就繼續執行完了
}

func main3() {
    c := make(chan bool)
    go func() {
        fmt.Println("GGGGGOOOOOO")
        c <- true //執行打印v,執行fmt.Println(v),
        close(c)  //關閉再也不迭代,不關閉則一直打印死鎖了
    }()
    for v := range c { //迭代channel的時候,一直在等待有值進去,才能夠取出來,在打印出來,
        fmt.Println(v)
    }
    /*
        GGGGGOOOOOO
        true
    */
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU()) //返回當前cpu的核數,並利用多核操做Goroutine(Goroutine是線程池)
    c := make(chan bool)
    for i := 0; i < 10; i++ {
        go GO1(c, i) //啓動9個goroutine
    }
    <-c //告訴main函數能夠退出了
}

func GO1(c chan bool, index int) {
    a := 1

    for i := 0; i < 100000000; i++ {
        a += 1
    }
    fmt.Println(index, a)
    if index == 9 { //啓動第九個goroutine的時候就能夠告訴main函數能夠退出了,
        //多核的時候index=9不必定是最後執行的,因此不必定會執行9遍,有可能執行一遍就退出了,解決方法:緩存的channel
        c <- true
    }
}

 

package main

import (
    "fmt"
    "runtime"
)

//緩存的channel
func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    c := make(chan bool, 10) //緩存的channel,緩存10個,
    for i := 0; i < 10; i++ {
        go GO1(c, i)
    }
    for i := 0; i < 10; i++ {
        <-c //取10次,就知道goroutine執行完了,這樣就保證了可以打印10 次
    }
}

func GO1(c chan bool, index int) {
    a := 1

    for i := 0; i < 100000000; i++ {
        a += 1
    }
    fmt.Println(index, a) //,這樣就保證了可以打印10 次
    c <- true             //存10次
}

/*
    9 100000001
    5 100000001
    0 100000001
    8 100000001
    7 100000001
    4 100000001
    1 100000001
    2 100000001
    6 100000001
    3 100000001
*/

 

package main

import (
    "fmt"
    "runtime"
    "sync" //有一個任務組,每完成一個任務就減一,等任務數爲0的時候任務就完成了
)

//第二種解決方案:同步,經過同步包實現多個Goroutine 打印內容
func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    wg := sync.WaitGroup{} //建立一個任務組
    wg.Add(10)             //添加10個任務

    for i := 0; i < 10; i++ {
        go GO1(&wg, i) //添加10個Goroutine
    }

    wg.Wait() //等待
}

func GO1(wg *sync.WaitGroup, index int) {
    fmt.Println(index) //打印就是一次任務
    wg.Done()          //任務完成一次
}

/*
    0 9 1 2 3 4 5 6 7 8
*/
相關文章
相關標籤/搜索