随笔

Goroutine And Channel

并发模型有进程级别的,有IO多路复用的,有线程的,有协程级别的。解释起来很啰嗦,参考第一条有一篇博文描述的挺形象的可以参考下。

goroutine

起一个goroutine非常简单,go后面跟执行的func即可。

go func()

需要注意任意一个goroutine panic都会使程序崩溃,所以注意recover(⊙o⊙)哦

defer func(){
    err := recover()
    xxxx
}

channel

字如其意,即通道。专门用来传输信息,然后是堵塞型的,即一次一条信息。

ch := make(chan int64)    // 声明
defer close(ch)           // 最后关闭 channel
ch <- variable            // 发送
variable := <- ch         // 接收
variable, isOpen:= <- ch  // 接收并返回 channel 是否已关闭

make第二个参数可以穿一个数字,代表缓存多少条消息,即不会像不设置时发送一条即堵塞等待接收。如果channel关闭后再执行发送动作,则会panic,接收者再去读取则会收到零值。

正常业务场景中会有同时执行好几个操作的时候(非幂等操作哦),这时候就可以用goroutine去分别执行,然后使用channel异步接收所有数据。

for {
    v := <- ch
}

这里用for来等待无限循环通道,指定数量只要设置for的终止条件即可。如果所有goroutine都已经关闭,而这里还未终止程序可是会报错的哦,所以一定要有一个终止条件。

select

ok 以上一直是一个channel,有的时候呢需要多个channel

for {
    select {
        case <- ch:
            // xxx
        case <- ch2:
            // xxx   
    }
}

sync

sync提供了一些魔术方法以便于我们简单快速的使用goroutine

WaitGroup

wg sync.WaitGroup
wg.Add(2)

go func1()
go func2()

func1() {
     defer wg.Done() // 告知已执行完毕一个
    // 逻辑
}

wg.wait() // 堵塞住,等待 wg.Done() 得到的信号数等于 Add 的数量

WaitGroup就像一个经过简单封装的线程安全的方法

atomic

当有多个goroutine想直接访问操作变量,而不使用通信时,就可能会出现资源竞争,以至于死锁。所以atomic提供了AddInt64, LoadInt64, StoreInt64等函数,这些函数可以保证在访问相同资源时,变成同步代码,排队去操作相同的资源。

mutex

另外还有一种互斥锁,mutex.Lock(), mutex.Unlock() 两个函数之间的代码将会成为一个独特的区域,同一时刻只会有一个goroutine在执行这段代码。

以上两个就分别类似于其它语言的安全方法,锁机制。

参考

https://www.cnblogs.com/guolei2570/p/8810536.html

本文链接:https://note.lilonghe.net//post/goroutine-and-channel.html

-- EOF --