• 区块链技术语言(二十八)——Go语言并发编程(下)


    本节紧接上一节的内容,主要介绍channel中的有缓冲channel、单方向的channel、定时器,以及select语句在channel中的应用。

    3.4 有缓冲的channel

    3.4.1 概述

    有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求goroutine之间必须同时完成发送和接收,通道会阻塞发送和接收动作的条件也不同:只有在通道中没有要接收的值时,接收动作才会阻塞;只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。有缓冲的通道和无缓冲的通道之间的最大不同在于:无缓冲通道保证发送和接收的goroutine会在同一时间进行数据交换;有缓冲的通道没有这种保证。图2通过示意图分析了多个goroutine利用有缓冲通道来共享一个值:
    a. 第1步,右侧的goroutine正在从通道中接收一个值;
    b. 第2步,右侧的这个goroutine独立完成了接收值的动作,而左侧的goroutine正在发送一个新值到通道里;
    c. 第3步,左侧的goroutine向通道发送新值,右侧的goroutine正在从通道接收另外一个值。这个步骤里的两个操作既不是同步的,也不会互相阻塞;
    d. 第4步,所有的发送和接收都完成,而通道里还有几个值,也有一些空间可以存更多的值。

    3.4.2 有缓冲的channel的创建

    如果给定了一个缓冲区容量,通道就是异步的。只要缓冲区有未使用空间用于发送数据,或者还包含可以接收的数据,那么其通信就会无阻塞地进行。有缓冲的channel创建格式如下:

    示例代码:

    3.5 单方向的channel

    3.5.1 概述

    channel默认双向。既可以向channel里发送数据,也可以从channel里接收数据。但是,要使channel作为参数传递且被单向使用,即只向该channel发送数据,或此channel只接收数据,那么需要对此channel指定方向。

    3.5.2 单向channel变量的声明

    单向channel变量有两种:一种是只能向channel里发送数据的变量,另一种是只能从channel里接收数据的变量。单向channel变量的声明格式如表2。

    注:

    a. chan<-表示把数据写入管道;
    b. <-chan表示将数据从管道中读取。

     

    3.5.3 channel的转换

    普通的channel可以隐式地转换为单向的channel,只接收数据或只发送数据;但是单向的channel不能转换为普通的channel。

    示例代码:

    四、select

    4.1 select语法结构

    Go语言关键字select可以监听channel上的数据流动。它的用法与switch语句类似,由select开始一个新的选择块,每个选择条件由case语句来描述。与switch语句可以选择任何可使用相等比较的条件相比, select有比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO(输入/输出)操作,它的语法结构如下:

    4.2 select语句执行顺序

    在select语句中,Go语言按顺序从头至尾评估每一个发送和接收的语句:
    如果其中任意一条语句可以继续执行(即没有被阻塞),那么就从那些可以执行的语句中任意选择一条来使用。

    如果没有一条语句可以执行(即所有的通道都被阻塞),那么有两种可能的情况:第一,如果有default语句,那么就会执行default语句,同时程序的执行会从select语句后的语句中恢复;第二,如果没有default语句,那么select语句将被阻塞,直到至少有一个case语句可以进行下去。

    在没有case准备就绪时,可以执行select语句中的default语句,这通常用于防止select语句一直阻塞。

    4.3 在select语句中设置超时

    当goroutine阻塞时,为避免整个程序进入阻塞,可以在select语句设置超时,具体通过如下方式实现:

    示例如下:

    参考资料:


  • 相关阅读:
    Delphi代码获取网卡物理地址三种方法 本文来自Delphi之窗,原文地址:http://www.52delphi.com...
    SQL SERVER 中实现公历到农历的转换
    cxgrid相同列合并显示
    rzCheckList.ItemChecked[Index]就可以判断指定节点地状态.
    为什么PING域名得到IP与实际公网IP不符
    如何让sql server2005和sql server2000共存安装在同一机器上
    如何编译通过 Raize 5.3 中的 RzBorder.pas
    u6升级到u890的过程
    技术部门到底该如何管理才能“和谐”
    在CXGRID中如何让字段能以0.00的格式显示
  • 原文地址:https://www.cnblogs.com/efish/p/go-language-concurrency2.html
Copyright © 2020-2023  润新知