热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从零开始学Go之并发(二):通道

由于goroutine中资源共享内存,为了避免互斥等问题保证数据正确性,引入通道的概念(channel)Go语言中的通道(channel)是一种特殊的类型。在任何时候,同时只能有一个gorou

由于goroutine中资源共享内存,为了避免互斥等问题保证数据正确性,引入通道的概念(channel)

Go 语言中的通道(channel)是一种特殊的类型。在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据。goroutine 间通过通道就可以通信。

通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。

 

声明:

var 通道变量名 chan 类型

var a chan int//一个数据类型为int的通道

chan 类型的空值是 nil,声明后需要配合 make 后才能使用。

 

创建:

通道是引用类型,需要使用 make 进行创建,格式如下:

通道实例名 := make(chan 类型)

var c2 chan int
c1 := make(chan interface{})
c2 = make(chan int)

 

发送数据:

通道变量 <- 值

c1 := make(chan interface{})
ch <- 0//0放入通道,需要接受否则会报错

把数据往通道中发送时,如果接收方一直都没有接收,那么发送操作将持续阻塞。Go 程序运行时能检查程序发现一些永远无法发送成功的语句并做出提示。

func main() {
 ch := make(chan interface{})
 // 将0放入通道中
 ch <- 0
 // 将hello字符串放入通道中
 ch <- "hello"
 fmt.Print(ch)
}

运行结果:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:

main.main()

D:/SoloWork/Learn/main.go:8 +0x76

 

接收数据:

通道的收发操作在不同的两个 goroutine 间进行,由于通道的数据在没有接收方处理时,数据发送方会持续阻塞

接收将持续阻塞直到发送方发送数据,如果接收方接收时,通道中没有发送方发送数据,接收方也会发生阻塞,直到发送方发送数据为止

通道一次只能接收一个数据元素。

 
阻塞接收数据

接收值 := <- 通道名

data := <-ch
 
非阻塞接收数据

接收值,判断通道是否已经被关闭 := <- 通道名

data, ok := <-ch

当通道被关闭后ok为false

 
接收任意数据,忽略接收的数据
<-ch

执行该语句时将会发生阻塞,直到接收到数据,但接收到的数据会被忽略。

这个方式主要用来通道在 goroutine 间阻塞收发实现并发同步。

 
循环接收

通道的数据接收可以借用 for range 语句进行多个元素的接收操作

for data := range ch {}

通道 ch 是可以进行遍历的,遍历的结果就是接收到的数据。数据类型就是通道的数据类型。通过for遍历获得的变量只有一个,即data

 

关闭通道:

close(通道名)

主要用于终止一个range循环。

只有发送者才能关闭信道,而接收者不能

发送者可通过close()关闭一个信道来表示没有需要发送的值了,接受者通过为接收表达式分配第二个参数来测试信道是否被关闭

 

单向通道:

var 通道实例 chan<- 元素类型 // 只能发送通道
var 通道实例 <-chan 元素类型 // 只能接收通道

单向通道是一个不能填充数据(发送)只能读取的通道,大多数时候是毫无意义的,主要用于保证代码接口的严谨性

 

缓冲通道:

将缓冲长度作为第二个参数提供给 make 来初始化一个带缓冲的信道:

通道实例名 := make(chan 类型,缓冲长度)

ch := make(chan int, 100)

当通道有缓冲后,仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接受方会阻塞。

带缓冲的通道在发送时无需等待接收方接收即可完成发送过程,并且不会发生阻塞,只有当存储空间满时才会发生阻塞。同理,如果缓冲通道中有数据,接收时将不会发生阻塞,直到通道中没有数据可读时,通道将会再度阻塞。(相当于操作系统里面的互斥初始量)

无缓冲通道可以看作是长度永远为 0 的带缓冲通道(即放入数据则开始阻塞发送,相当于互斥量为1)

 


推荐阅读
  • 认真一点学 Go:18. 并发
    收录于《Go基础系列》,作者:潇洒哥老苗。>>原文链接学到什么并发与并行的区别?什么是Goroutine?什么是通道?Goroutine如何通信?相关函数的使用?sel ... [详细]
  • Channel是Go中的一个核心类型,你可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯(communication)。类型T表示任意的一种类型双向:chan ... [详细]
  • 按照之前我对map的理解,map中的数据应该是有序二叉树的存储顺序,正常的遍历也应该是有序的遍历和输出,但实际试了一下,却发现并非如此,网上查了下,发现从Go1开始,遍历的起始节点就是随机了,当然随机 ... [详细]
  • golang 解析磁力链为 torrent 相关的信息
    其实通过http请求已经获得了种子的信息了,但是传播存储种子好像是违法的,所以就存储些描述信息吧。之前python跑的太慢了。这个go并发不知道写的有没有问题?!packag ... [详细]
  • Go 快速入门指南命令行参数
    命令行参数个数调用os包即可。获取参数个数,遍历参数packagemainimport(fmtos)funcmain(){fmt.Printf(Numberofargsi ... [详细]
  • BZOJ1233 干草堆单调队列优化DP
    本文介绍了一个关于干草堆摆放的问题,通过使用单调队列来优化DP算法,求解最多可以叠几层干草堆。具体的解题思路和转移方程在文章中进行了详细说明,并给出了相应的代码示例。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 本文介绍了协程的概念和意义,以及使用greenlet、yield、asyncio、async/await等技术实现协程编程的方法。同时还介绍了事件循环的作用和使用方法,以及如何使用await关键字和Task对象来实现异步编程。最后还提供了一些快速上手的示例代码。 ... [详细]
  • funcReadXlsx(c[]CmdbTest,SheetNamestring)error{打开文件,如果文件不存在创建,存在就打开path:.cm ... [详细]
  • 目录在Go语言项目中使用Zap日志库介绍默认的GoLogger日志库实现GoLogger设置Logger使用LoggerLogger的运行GoLogger的优势和劣势优势劣势Ube ... [详细]
  • Go冒泡排序练习
    package main要求:随机生成5个元素的数组,并使用冒泡排序对其排序  从小到大思路分析:随机数用mathrand生成为了更好 ... [详细]
  • [Redis 系列]redis 学习六,redis 事务处理和监控事务
    【Redis系列】redis学习六,redis事务处理和监控事务写在前面我们学过的事务都是保证原子性的,但是redis的事务中执行多个指令,是不保证原子性的redis事务的本质就是 ... [详细]
  • 集成第三方库,自检测读取配置文件。文件读取,结构体定义,接口实现,错误返回,库解析,适合新同学练手。思路文件读取获取字节流文件类型分析,确定解析api集成第三方解析api管理器定义 ... [详细]
  • 20220811:以下go语言代码输出什么?A:panic;B:编译错误;C:json marshal 报错
    2022-08-11:以下go语言代码输出什么?A:panic;B:编译错误;C:jsonmarshal报错;D:null;E:nil。packagemainimport(enc ... [详细]
author-avatar
忘不了那个你
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有