Go并发

xiongkun01 · · 597 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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
}



有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:xiongkun01

查看原文:Go并发

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

597 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传