当前位置: 首页 > article >正文

深入理解 Go 语言并发编程--管道(channel) 的底层原理

        管道是 Go 语言协程间通信的一种常用手段,管道的读写操作也有可能会阻塞用户协程,也就是说有可能会切换到调度器。协程因为管道而阻塞时,只有当其他协程再次读或者写管道时,才有可能解除这个协程的阻塞状态。

1. 管道的基本用法

        管道是 Go 语言协程间通信的一种常用手段,可以分为无缓冲管道和有缓冲管道。因为无缓冲管道本身没有容量,不能缓存数据,所以只有当协程在等待读时,写操作才不会阻塞协程;或者当有协程在等待写时,读操作才不会阻塞协程。因为有缓冲管道本身有一定容量,可以缓存一定数据,所以当协跑第一执行写操作时,即使没有其他协程在等待读,只要管道还有剩余容量,写操作就不会阻塞协程;或者当协程执行读操作时,即使没有其他协程在等待写,只要管道还有剩余数据,读操作就不会阻塞协程。

        下面写一个简单的 Go 程序,学习管道的基本用法,代码如下所示:

package main

import (
	"fmt"
	"time"
)

func main() {
	queue := make(chan int, 1)
	go func() {
		for {
			data := <-queue     //读取
			fmt.Print(data, "") //0 1 2 3 4 5 6 7 8 9
		}
	}()

	for i := 0; i < 10; i++ {
		queue <- i //写入
	}
	time.Sleep(time.Second)
}

        参考上面代码,主协程循环向管道写入整数,子协程循环从管道读取数据。主协程休眠 1s 是为了防止主协程结束,整个 Go 程序退出,导致子协程也提前结束。函数 make 用于初始化 Go 语言的一些内置类型,如切片 slice、散列列 map 以及管道 chan。注意用函数 make 初始化时,第一个参数 chan int 表示管道只能用来传递整型数据,第二个参数表示管道的容量是 1,即最多只能缓存一个整型数据。

        管道的操作还是比较简单的,无非就是读、写以及关闭操作。这里提出一个问题,如果程序没有初始化管道,却执行读或者写操作会发生什么呢?或者说,如果一个管道已经被关闭了,这时候执行读或者写操作会发生什么呢?我们写一些简单的 Go 程序测试一下。

        第 1 个程序:不初始化管道,直接


http://www.kler.cn/a/280174.html

相关文章:

  • 百度搜索的RLHF性能优化实践
  • 14.JS学习篇-CSR和SSR
  • 深入理解Spring Boot中的@ConditionalOnProperty注解及其应用
  • 【书生大模型实战营(暑假场)】进阶任务三 LMDeploy 量化部署实践闯关任务
  • 深度学习100问10-什么是CBOW模型
  • 后端开发刷题 | 合并k个已排序的链表
  • Docker常见命令和参数
  • 2、LVGL控件-标签、按钮
  • uni-app开发日志:schema2code生成的新增页和修改页因字段太多用分段器实现分段分类
  • abc 366 E+F(曼哈顿距离 x y 两个坐标分别计算)(贪心+01背包)
  • 微前端架构:使用不同框架构建可扩展的大型应用
  • Pytest框架直接右键运行 testcase.py,不执行最外层conftest
  • webserver.h详解
  • vector相关功能的底层实现
  • OpenHarmony Camera源码分析
  • ARM程序的组成和执行过程
  • vue3的nginx配置文件配置(nginx只配置前端vue3的nginx.conf文件)
  • 计算机专业的真正的就业情况
  • OpenCV绘图函数(2)绘制圆形函数circle()的使用
  • Godot《躲避小兵》实战之游戏开始界面制作