C#/JAVA 程式員轉GO/GOLANG程式員筆記大全(DAY 06)

來源:互聯網
上載者:User

----------------------------------------- go 並發

// 註解:go 語言天生為程式並發所設計,可以說go的強項就是在cpu並發上的處理。// go 語言層面就支援了並發。(不是一般進階語言的多線程並發,是系統級真實並發)// go 語言通過安全的通道發送和接受資料以實現同步// 一般情況下,一個普通的案頭電腦跑十幾二十幾個線程就有點負載過大了,但是同樣的硬體裝置go可以輕鬆上K。

 

----------------------------------------- goroutine

// 註解:go 並發設計的核心,goroutine在並發中起到的作用就是協程(CSP),但是它比線程更小。(協程=微線程)// go 不支援後台協程,意思就是主程式退出,協程跟著一起退出func newTask() {    for {        fmt.Println("new task ...")        time.Sleep(time.Second) // 休眠1s    }}func main() {    go newTask()    // 建立一個協程,建立一個任務        for {        fmt.Println("main ...")        time.Sleep(time.Second) // 休眠1s    }}// result : // main... // new task ...// ....

 

----------------------------------------- gosched

// 註解:讓出CPU時間片,讓出當前 gorotine 的執行許可權,// 調度器安排其他等待任務運行,並在下次某個時候從該位置恢複執行。func main() {    go func() {        for i := 0; i < 5; i++ {            fmt.Println("go")        }    }()        for i := 0; i < 2; i++ {        fmt.Println("hello")    }        // 這種情況,匿名函數未得到執行程式就結束了。        // 時間片案例示範代碼,修改如下:    for i := 0 .... {        runtime.Gosched()        fmt.Println("hello")    }    // 執行結果:    // go go ... hello ..}


----------------------------------------- goexit

import "runtime"// 註解:終止所在的協程 (所在的協程不是當前函數)func test() {    defer fmt.Println("ccccc")        runtime.Goexit()    fmt.Println("dddd")}func main() {    go func (){        fmt.Println("aaaa")        test()        fmt.Println("bbbb")    }    for {    }        // result:    // aaaa  cccc}

 

----------------------------------------- gomaxProcs

// 註解:設定可以並行計算的 CPU 核心數的最大值import "runtime"func main() {    n := runtime.GOMAXProcs(1)    //制定以1核運算    fmt.Println("n = ", n)        for {        go fmt.Print(1)            fmt.Print(0)    }        // 列印結果:11111.. 一大片, 00000...一大片    // 如果設定 GOMAXProcs(4) 為 4 核交叉效果更好}


----------------------------------------- 資源爭奪問題 channel

// 註解:channel 也是一種資料類型,同步// 文法:channel <- value     // 發送 value 資料到 channel// <- channel                 // 接收並丟棄// 案例:// 全域變數,建立一個 channelvar ch = make(chan int)// 定義一個印表機,參數為字串,按每個字元列印func Printer(str string) {    for _, data := range str {        fmt.Printf("%c", data)        time.Sleep(time.Second)    }    fmt.Printf("\n")}func person1() {    Printer("loong print")    ch <- 666        // 給管道寫資料}func person2() {    <- ch            // 從管道取資料,如果管道沒有資料前他就會阻塞    Printer("make print")}func main() {    // 建立 2 個協程,代表 2 個人,2 個人同時使用印表機    go person1()    go person2()}// 註解: 【認真看】// 沒有 channel 的情況// 列印結果混亂,person1 列印一個h,person2 列印一個 w,交叉了。不符合我們的要求// 增加 channel ,則在 <-ch 的地方進行了阻塞,通過進、出的方式融合這種解決這種並發互搶資源的問題。


----------------------------------------- channel 實現同步和資料互動

fun main() {    ch := make(chan string)        defer fmt.Println("主協程也結束")        go func() {        defer fmt.Println("子協程調用完畢。")                for i := 0; i < 2; i++ {            fmt.Println("子協程 i=", i)            time.Sleep(time.Second)        }                ch <- "我是子協程,工作完畢"    }        str := <-ch // 沒有資料前,阻塞    fmt.Println("str = ", str)}// 注意:程式需求:主程式結束之前,能夠完整執行匿名函數中的代碼// 使用 channel 配合完成


----------------------------------------- channel 無緩衝&有緩衝

c1 := make(chan int)         無緩衝c2 := make(chan int,1)      有緩衝c1 < -1                            // 無緩衝:不僅僅是向 c1 通道放 1,// 而是一直要等有別的協程 <-c1 接手了這個參數,那麼c1<-1才會繼續下去,要不然就一直阻塞著。// 有緩衝: c2<-1 則不會阻塞,因為緩衝大小是1(其實是緩衝大小為0),// 只有當放第二個值的時候,第一個還沒被人拿走,這時候才會阻塞。// 不需要再使用記得關閉channel  close(c1)// 判斷管道是否關閉 if num, ok := <- c1; ok == true { // 關閉了 }----------------------------------------- channel 單方向var ch1 chan int        // ch1 是一個正常的 channle,不是單向的var ch2 chan<- float64    // ch2 是單向 channel,只用於寫 float64 資料var ch3 <-chan int        // ch3 是單向 channel,只用於讀取 int 資料// * 管道的操作,一定要避免死結的情況。


----------------------------------------- channel 應用

// 此案例可以應用很多情境,每寫一個,則可以消耗一個// 此通道只能寫,不能讀func producer(out chan<- int) {    for i := 0; i < 10; i++ {        out <- i * i    }        close(out)}// 此通道只能讀,不能寫func consumer(in <-chan int) {    for num := range in {        fmt.Println("num = ", num)    }}func main() {    // 建立一個雙向通道    ch := make(chan int)        // 生產者,生產數字,寫入 channel    // 開啟一個協程    go producer(ch)        // 消費者,從channel讀取內容列印    consumer(ch)}

 

----------------------------------------- Timer

import (    "time"    "fmt")func main() {    // 建立一個定時器,設定時間為2s,2s後,往time通道寫內容    timer := time.NewTimer(2 * time.Second)    fmt.Println("目前時間:", time.Now())        // 2s後,往timer.C寫資料,有資料後讀取    t := <-time.C    // channel 沒有資料前後阻塞    fmt.Println("t = ", t)}


----------------------------------------- select

// 註解:go語言提供了一個關鍵字 select,通過 select 可以監聽 channel 上的資料流動// 文法:(類似 switch)select {    case <-chan:        // 如果channel 成功讀到資料,則進入 case 塊語句    case chan<- 1:        // 如果channel 成功寫到資料,則進入 case 塊語句    default:        // 如果上面都沒有成功,則進入default處理流程        // 注意:慎用,很消耗 cpu}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.