Go channel 边写边读和一次性写一次性读(有无缓冲)

有缓冲 (边写边消费)

当channel 容量 和 消费生产容量相同时,不会发生阻塞,我们看这里

package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan int, 3)
	fmt.Println("len c is ", len(c), "cap c is ", cap(c))

	go func() {
		defer fmt.Println("sub go is dnoe!")

		for i := 0; i < 3; i++ {
			c <- i
			fmt.Println("sub-go is running sending element", i, "Len c is", len(c), "cap c is ", cap(c))
		}
	}()

	time.Sleep(2 * time.Second)
	for i := 0; i < 3; i++ {
		num := <-c
		fmt.Println("num is ", num)
	}
	fmt.Println("main done!")

}

Lux@Luuuxury Go% go build channel.go 
Lux@Luuuxury Go% ./channel 
len c is  0 cap c is  3
sub-go is sending element 0 Len c is 1 cap c is  3
sub-go is sending element 1 Len c is 2 cap c is  3
sub-go is sending element 2 Len c is 3 cap c is  3
sub go is dnoe!
num is  0
num is  1
num is  2
main done!

如果我们把容量 c := make(chan int, 3) 改成 2,运行结果如下(每个人的输出顺序可能不一样)

len c is  0 cap c is  2
sub-go is sending element 0 Len c is 1 cap c is  2
sub-go is sending element 1 Len c is 2 cap c is  2
num is  0
num is  1
sub-go is sending element 2 Len c is 2 cap c is  2
sub go is dnoe!
num is  2
main done!

无缓冲 (一次性写,一次性读)

func main() {
	c := make(chan int, 5)
	fmt.Println("len c is", len(c), "cap c is ", cap(c))
	go func() {
		for i := 0; i < 5; i++ {
			c <- i
		}
		close(c)
	}()
	for { 
		if data, ok := <-c; ok {
			fmt.Println(data)
		} else {
			break
		}
	}
}

运行

len c is 0 cap c is  5
0
1
2
3
4

这里主线程和子协呈程做呼应的其实是 close 和 ok, 添加close ,当子协程运行完后close,后通过ok判断 channel 是否还有数据。如果我们把close去掉,运行

len c is 0 cap c is  5
0
1
2
3
4
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

当channel 为空时候,又由于消费者的持续读取,发生死锁

当然这里也可以 简化 if data, ok := <-c; ok {,也可以使用range来迭代操作channel,如下

for data := range c {
    fmt.Println(data)
}

效果也是一样的

其他参考

类比操作系统里面的PV操作

mutex = 1 作为互斥量 ; empty = n 自定义容量 ; full 初始值为 0

生产者:

P(empty)
P(mutex)
放入
V(mutex)
V(full)

消费者

P(full)
P(mutex)
取出
P(mutex)
V(empty)

如果互斥在前,同步在后, 当前容器放满了(只能等待消费了), 那么会出现, P生产(mutex), --> P生产(empty) - 此时没有空位, --> 生产者阻塞,转到消费者 P消费(mutex), 被生产者互斥阻塞, 所以, 必须同步P在前, 互斥P在后

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值