zoukankan      html  css  js  c++  java
  • go channel 原理

    大家或多或少的接触过了channel 了,我今天想学一下channel的数据结构。

    我有的时候喜欢从一个对象提供的公共接口/功能来猜测这个对象的数据结构,那么今天我们来猜一猜channel。

    1,channel可以存储数据,而且是先进先出,所以我猜测其中包含一个数组或者链表之类的用来保存数据。

    2,channel可以多线程的读写,所以应该还有一个锁,来支持并发。

    3,然后应该还会有一些 长度的属性。

    4,close 一个closed的channel 会panic,所以有一个状态字段保存是否closed,比较科学。

    5,保存数据的数组或者的链表应该是定长的,最起码应该有一个最大长度,不然的话,就可以一直无限写入channel,

    大致的猜测结果有了,那我们来看一下channel是怎么定义的?

    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
    }

    可以看到,猜到的部分,基本正确。那我们现在来仔细说说这个结构。

     首先,我们定义一个channel

    ch := make(chan int, 2)
    当使用
    <-ch
    ch<- 的时候,就会使用mutex锁住这个ch。然后把数据从goruntine copy到 ch/把数据从ch copy到goruntine,最后释放锁。
    这样就可以实现通过交流来共享内存。Do not communicate by sharing memory;instead,share memory by communicating。

    当ch满了之后,继续使用ch<-,当前goruntine 会阻塞,

    当ch空了之后,继续使用<-ch,当前goruntine 也会阻塞。

    但是,当前goruntine被阻塞之后,什么时候会被唤醒呢?
    但send 阻塞时,goruntine和send的值会被封装成sudog,放到sendq中等待,
    当rev之后,这时候ch不在是满的,sendq 等待列表中的一个数据sudog取出来放到ch中,然后阻塞的goruntine被唤醒
    type waitq struct {
    first *sudog
    last *sudog
    }


    当ch为中的时候,继续send,也会阻塞,但是接着rev操作和上面略有不同
    rev并不锁住ch,而是直接将数据copy给sendq列表中的一个,这样减少了部分锁,增加了效率,确实巧妙
    
    
  • 相关阅读:
    ECharts学习总结(四):echarts的实例方法
    ECharts学习总结(三):ECharts图表对象的初始化(init)详解以及注意事项
    ECharts学习总结(二):标签式单文件引入echarts的方法
    ECharts学习总结(一):ECharts的第一个图表
    Eclispe最常用的几个快捷键
    javascript数组去重的4个方法(转)
    数据库主键设计之思考(转)
    数据库插入数据返回当前自增主键ID值的方法
    Node.js制作图片下载爬虫的一般步骤
    Node.js mzitu图片批量下载爬虫1.00
  • 原文地址:https://www.cnblogs.com/13579net/p/11077244.html
Copyright © 2011-2022 走看看