golang笔记:三句话小结使用通道(chan)控制协程同步的用法。

本文介绍了Go语言中通道的使用,包括无缓存通道和有缓存通道的工作原理。在无缓存通道中,发送和接收会互相阻塞,而在有缓存通道中,当缓存满或空时,相应操作会阻塞。通过示例代码展示了如何利用有缓存通道限制并发数量,确保并发安全。通道的这一特性在并发控制和任务调度中具有重要作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.无缓存的通道,谁先到谁阻塞。

——无缓存通道的情形下,接收方(<-c1)和发送方(c1 <- true )会互相等待。

  • 也即:如果接收方走到 <-c1 而发送方没有走到c1 <- true,则接收方协程会阻塞,等待发送方执行完c1 <- true 双方协程才会共同继续。反之亦然。
  • 此时发送方和接收方的代码可以互换,不影响逻辑的进行。(但仍然建议由主协程或母协程来作为接收方)
2.有缓存的通道,塞满时发送方阻塞。

——有缓存通道的情形下,如果缓存已满,会阻塞发送方的协程。

  • 直到有接收方取出信息(也即执行 <-c1 ),为后续信息腾出空位。
3.有缓存的通道,拿空后接收方阻塞。

——有缓存通道的情形下,如果缓存为空,会阻塞接收方的协程。

  • 直到有发送方存入信息(也即执行c1 <- true)。

相关代码如下

var c1 = make(chan bool)
func func1() {
	//...  
	c1 <- true  
	//...  
}

func main() {
	go func1()
	
	//...  
	<-c1
	//...  
	select {} //保证协程结束
}
扩展应用:用缓存通道控制并发数目
  • 本质是上文中 2. 的机制的运用
  • 在大量并发的子协程的入口处使用c1 <- true,利用上文中2. 的机制阻塞新协程的开启;并在执行完毕后执行 <-c1,腾出缓存中的空间,此时则会放行某一个阻塞中的c1 <- true完成执行,进入后续步骤。如此宏观上的表现即为通道c1中定义的缓存项数量等于所允许的子协程并发量的上限。

示例代码:

package main

import (
	"time"
)

var limit = make(chan int, 3)

func main() {

	for i := 0; i < 20; i++ {

		limit <- 1 //缓存有空间,或接收方有就绪的,才会继续往下走
		println("循环次数--", i)

		go func(i int) { //同时也是协程持有的是引用的示例

			//println("func-", i, "阻塞中")
			//limit <- 1 //阻塞的代码也可以写在子协程生成后

			println("执行中--", i)
			time.Sleep(2 * time.Second)
			println("       ", i, "--执行完成")
			<-limit

			//也即,从传入到传出的中间这段,同时只能存在3个运行中,第四个的limit <- 1会等第一批的三个中有一个走到<-limit才能继续(也即释放了一个chan的缓存|缓存有了空间,可以接收新的传入)

		}(i)
	}

	select {}
}

观察结果可知,当缓存通道被占满后,每有一个“执行完成”,“循环次数”才会往下走一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值