Golang channel了解吗,channel的工作原理是什么?

Go不推荐用共享内存方式来通信,推荐使用通信的方式来共享内存

channel用于多个goroutine之间传递数据,且保证整个过程的并发安全性。

channel是Go特有一种数据结构,可以理解为一个管道。

管道分为无缓存的管道和有缓存的管道。

Go语言内存模型规范,对于从无缓冲Channel进行的接收,发生在对该Channel进行的发送完成之前。也就是说,无缓存管道,发送和接收是同步的,任意一个操作都无法离开另一个操作单独存在。否则就会发生deadlock死锁。

package main
import "fmt"
func main() {
	done := make(chan int)
	var a string
	go func(){
		a = "hello"
		<-done
	}()
	done <- 0
	fmt.Println(a)
}

以上程序Goroutine中的 <-done接收操作和main中的done <- 0发送操作同步进行,管道同步操作为赋值和打印明确了顺序,所以保证了a先被赋值”hello“,然后输出。同理,将发送和接收换位置,程序运行结果一致。

package main

import "fmt"

func main() {
	done := make(chan int)
	var a string


	go func(){
		a = "hello"
		done <- 0
	}()
	<-done
	fmt.Println(a)
}

对于带缓冲的Channel,对于Channel的第K个接收完成操作发生在第K+C个发送操作完成之前,其中C是Channel的缓存大小。也就是说发送和接收操作可以不同步,当通道中没有要接收的值时,接收动作会阻塞;当通道缓冲区满时发送操作会阻塞。

package main

import "fmt"

func main() {
	done := make(chan int, 1) //带缓存
	var a string

	go func(){
		a = "hello"
		done <- 1
	}()

	<-done
	fmt.Println(a)
}

因为接收会阻塞等到发送数据完成,所以a先被赋值”hello“,然后输出。此时当我们把发送和接收换位置:

package main

import "fmt"

func main() {
	done := make(chan int, 1)
	var a string

	go func(){
		a = "hello"
		<-done
	}()

	done <- 1
	fmt.Println(a)
}

运行发现输出为空,这是因为带缓存的通道,在通道缓存还有空间时,发送操作直接完成,所以主程序会先于Goroutine完成退出。

综上,我们其实可以简单的将管道工作理解为:无缓存通道,发送接收需同步;有缓存通道,发送接收可以阻塞等待。

参考:https://zhuanlan.zhihu.com/p/272479809

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值