Golang 之channel

2018-10-18  本文已影响0人  davisgao

1.channel 的特性

2.channel 的结构

image.png
type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements 指向一个环形队列
    elemsize uint16
    closed   uint32
    elemtype *_type // element type
    sendx    uint   // send index
    recvx    uint   // receive index
    recvq    waitq  // list of recv waiters
    sendq    waitq  // list of send waiters

    // lock protects all fields in hchan, as well as several
    // fields in sudogs blocked on this channel.
    //
    // Do not change another G's status while holding this lock
    // (in particular, do not ready a G), as this can deadlock
    // with stack shrinking.
    lock mutex
}

3.channel的发送和接收

image.png

3.channel实现阻塞和非阻塞

如果一直往channel中发送task,那么当channel满时,就会导致发送者(goroutine )的执行暂停。暂停的过程如下:

一个线程持有一个P,P持有执行队列

goroutine 阻塞,但是对应的OS的Thread不会阻塞,同时一个Thread管理的一组goroutine 不会引起线程的上下文切换
如何恢复G1的运行,但是其他的goroutine 一旦开始接收channel中的数据时(channel就不满了),此时需要恢复channel的发送者goroutine

4.goroutine 的暂停

pause.png

goroutine的暂停(例如上述的阻塞),chan会通知调度器来暂存goroutine,并将其状态从运行态修改成等待状态,同时从p中调度新的goroutine。

5.goroutine 的恢复

resume.png

6.直接发送

direct.png

当G1需要被恢复时,从理论上说,需要获取chan的锁,但是runtime此处有个优雅的设计,使其代价更小。runtime直接把G1复制到接收队列G2的栈中,不需要获取chan的锁。也不需要从chan中进行内存的拷贝。

7.总结

单向chan,约束方法参数:
例如在接受方的chan设置成只读,可以约束chan无法关闭

上一篇下一篇

猜你喜欢

热点阅读