channel:

channel一种个安全的双端队列,任何任务只要持有channel的引用,就可以向一端加入消息,也可以向一端删除消息,消息的消费者和生产者不清楚对方是谁。

channel分为无缓冲和有缓冲,无缓冲会同步阻塞,即每次生产消息都会阻塞到消费者将消息消费;有缓冲的不会立刻阻塞。

关闭channel:向关闭的channel读数据会是nil,向关闭的channel写数据会被弃用。

channel缓冲区已满的处理策略:

  1. 默认策略是阻塞写消息,直至写成功
  2. dropping-buffer:缓冲满后忽略最迟的消息
  3. sliding-buffer:缓冲满后弃用最早的消息
  4. 为什么不支持容量自动扩展的channel:有限的资源总有会遇到资源耗尽的时候,如果因为各种外来内在原因而出现消息堆积的场景,在重重代码种会变成非常难排除的bug,所以最好的处理方案,就是在任何场景使用缓冲的channel,必须考虑缓冲溢出如何处理

go 块

线程在其他语言比如Java的使用方案,首先可以单独创建线程处理任务,因为线程重复创建销毁会带来很多的性能开销,所以首选使用线程池技术,但是线程池技术在线程通信的时候,还有其他缺陷比如,如果线程被阻塞,这个线程将被无限期占用,这个在高并发的场景下,削弱了线程池的优势。
如果要补全这个缺陷,也有其他的解决方案比如事件驱动,仅仅当被通知IO准备好时,线程才会去处理这个IO请求,这个方案可以实现但是会限制代码的编写风格,使用复杂,可读性非常差。
go块从根本提供了解决方案,在底层通信代码中,将底层串行通信的代码重写为事件驱动的代码(channel?),而上层业务代码无需考虑IO切换,就能实现灵活的线程阻塞时的切换。
控制反转:go块代码是一个状态机,当读写channel时,会将go块状态变为暂停,主动让出线程,等待go块继续运行的时候,会请求已有或新线程,然后状态转换后继续运行。
意义:不用担心资源而随意创建并发任务。

10-07 16:41