Golang实现Redis(4):关于channel和协程的一点点理解

事情的起因是这样的,我看到了channel有阻塞的特性,我最开始内心的想法是
👍👍👍👍👍👍,实际上是😢😢😢😢😢😢

iChan := make(chan int)
<-iChan
fmt.println("输出")
//或者 iChan<-1
//fatal error: all goroutines are asleep - deadlock!
终端会一直阻塞,会出现光标一直闪烁的情况,后来我发现我太单纯了
最后我实验了无缓冲的管道读写和有缓冲的管道读写
fmt.Println("一个没有缓冲的空管道,写入数据,没有接收,会出现什么情况,阻塞 还是死锁  也是会出现死锁")
fmt.Println("一个没有缓冲的空管道,读取数据,会阻塞吗,还是死锁  会死锁")
fmt.Println("一个有缓冲的空的管道,读取时,会阻塞嘛 会出现死锁")
fmt.Println("一个有缓冲的空管道,写入一条数据,会出现什么情况,不会阻塞,不会思索,会正常执行之后的代码")
我开始懵逼了,于是我开始各种搜索引擎,大多讲的是特性。
我想说几句我对上面两行代码的理解 为什么会出现死锁
//一句话阻塞导致死锁
//go在解析的时候发现在一个主协程中,发现永远不能输出,结果就是死锁
iChan := make(chan int)
go func() { //给他起个名字:协程一
	iChan <- 1	//堵塞
}()
fmt.Println(<-iChan)  //这行就叫燕子吧 
time.Sleep(1)
紧接着我把代码改成这样 发现会正常输出,我就离了个大谱。
不是说好永远不分开的吗,不对,不是说好阻塞的吗,阻塞变死锁不说.
加了个goroutine就可以了,这是为啥.

我仔细想了一下,协程一在旁边执行 给无缓冲的管道写入数据,但是没有接收
我们想一下,会变成,阻塞
我就更懵逼了,不是说好了燕子堵塞吗,你啷个相互阻塞啥个意思嘛,
到现在我都不理解,但是呢 确实输出了个结果:1 
事情说到这我以为我就带着这个疑问睡觉了.我就想着把main协程,改成其他协程
于是我又改成了这样

	iChan := make(chan int)

	go func() {
		iChan <- 1
		fmt.Println("应该是输出这行,然后输出1")
	}()

	go func() {
		fmt.Println(<-iChan)
		fmt.Println("然后输出这样")
	}()

	time.Sleep(1)
	
	输出结果没什么问题
PS D:\goproject\src\practice> go run main.go
应该是输出这行,然后输出1
1
然后输出这样

这里就出现了我认为的一个问题,相互堵塞的两个协程,谁会先执行呢?
这里我尝试说一下我自己的理解,管道有堵塞的特性,堵塞的这种特性其实会导致协程的代码执行
这里我说两个相互阻塞的协程,我们拆开看。
先说一点,默认情况下,channel的接收和发送都是阻塞的,除非另一端已准备好。
那也就是说,这两个协程,无论谁先执行,都会进入阻塞,所以就意味着,一个堵塞,一个准备好,就切换执行了,
协程的调度时机往往都在堵塞和协程全部执行完成。
紧接着我就看到了这行代码

var wg sync.WaitGroup
var printChar chan int

func printNums() {
	defer wg.Done()
	for i := 0; i < 2; i++ {
		printChar <- 1111        //第一次一定是阻塞到这的
		fmt.Println(<-printChar) 
		// 1111被读取之后,这里因为又没有数据
		// 所以还是阻塞
	}
}

func printChars() {
	defer wg.Done()
	for i := 0; i < 2; i++ {
		fmt.Println("阻1") 
		//阻1 1111 阻2  出来1  出来2
		// 阻1 1222 1111 阻2 出来1 出来2
		fmt.Println(<-printChar)
		fmt.Println("阻2")
		fmt.Println("出来1")
		printChar <- 1222
		fmt.Println("出来2")
	}
}

func main() {
	printChar = make(chan int)
	
	wg.Add(2)
	
	go printNums()
	go printChars()
	
	wg.Wait()
}

输出结果
//阻1 1111 阻2  出来1  出来2  阻1 1222 1111 阻2 出来1 出来2

大家如果看到这可以去打印一下
最终我是得到了一个结论

前提场景是:一个协程先执行(A),那么这个协程会在什么时候让出控制权呢
答案是,A协程先执行,B协程堵塞的情况下,A协程会在遇到阻塞的时候让出控制权
而不是,当在A协程中给阻塞的B协程处理完之后,就会让出控制权,并不是.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值