Go併發

package main

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

var c int

func counter() int {
    c++
    return c
}

func main2() {
    a := 100

    go func(x, y int) {
        time.Sleep(time.Second)
        println("go:", x, y)
    }(a, counter())

    a += 100
    println("main:", a, counter())

    time.Sleep(time.Second * 3)
}

// 進程退出不會等待併發任務結束,可用通道阻塞,而後發出退出信號
func main3() {
    exit := make(chan struct{})

    go func() {
        time.Sleep(time.Second)
        println("goroutine ....")

        // 除關閉通道外,寫入數據也可接觸通道
        close(exit)
    }()

    println("main ....")
    <-exit
    println("main exit.")
}

// 等待多個併發任務結束,使用sync.WaitGroup
func main4() {
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1) // 累加計數

        go func(id int) {
            defer wg.Done() // 遞減計數

            time.Sleep(time.Second)
            println("goroutine", id, "done.")
        }(i)
    }

    println("main ...")
    wg.Wait()
    println("main exit.")
}

// 可在多處使用wait,它們都能接收到通知
func main5() {
    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
        wg.Wait() // 等待歸零,解除阻塞
        println("wait exit.")
    }()

    go func() {
        time.Sleep(time.Second)
        println("done.")
        wg.Done()
    }()

    wg.Wait() // 等待歸零,解除阻塞
    println("main exit.")
}

func main7() {
    var wg sync.WaitGroup
    var gs [5]struct {
        id     int
        result int
    }

    for i := 0; i < len(gs); i++ {
        wg.Add(1)

        go func(id int) {
            defer wg.Done()

            gs[id].id = id
            gs[id].result = (id + 1) * 100
        }(i)
    }

    wg.Wait()
    fmt.Printf("%+v\n", gs)
}

// Gosched 暫停,釋放線程去執行其餘任務。當前任務被放回隊列,等待下次調度時恢復執行
func main8() {
    runtime.GOMAXPROCS(1)
    exit := make(chan struct{})

    go func() {
        defer close(exit)

        go func() {
            println("b")
        }()

        for i := 0; i < 4; i++ {
            println("a:", i)

            if i == 1 { // 讓出當前線程,調度執行 b
                runtime.Gosched()
            }
        }
    }()

    <-exit
}

// Goexit 當即終止當前任務,運行時確保全部已註冊延遲調用被執行
// 不管身處哪一層,Goexit 都能當即終止整個調用棧,這與return僅退出當前函數不一樣
// 標準庫函數 os.Exit 可終止進程,但不會執行延遲調用
func main9() {
    exit := make(chan struct{})

    go func() {
        defer close(exit)
        defer println("a")

        func() {
            defer func() {
                println("b", recover() == nil)
            }()

            func() {
                println("c")
                runtime.Goexit() // 當即終止整個調用棧
                println("c done.")
            }()

            println("b done.")
        }()

        println("a done.")
    }()

    <-exit
}
相關文章
相關標籤/搜索