Channel有缓冲和无缓冲区别(fatal error: all goroutines are asleep - deadlock!问题)

概念这里我们不多赘述,直接看实际开发中它的区别。   

首先我们看无缓冲通道

package main

import (
	"fmt"
	"test/channeltest/ano"
	"time"
)

// 接收消息函数
func receiveMessage(ch <-chan string) {
	msg := <-ch
	fmt.Println("接收到消息:", msg)
}

// 发送消息函数
func sendMessage(ch chan<- string, msg string) {
	ch <- msg
	fmt.Println("发送消息:", msg)
}
func main() {\
	// 创建通道
	ch := make(chan string)

    // 发送消息
	sendMessage(ch, "Hello, test!")
    // 启动接收消息的 goroutine
	go receiveMessage(ch)

	// 保持程序运行,等待接收消息
	time.Sleep(3 * time.Second)

}

报错:出现死锁

分析原因:

        因为是无缓冲通道,他需要有协程去接收它,而在上面的代码中,先执行了发送的代码,接收的代码还没有执行导,也就是没有接收消息的协程,所以会卡死。

将代码换成

	go sendMessage(ch, "Hello, test!")
	go receiveMessage(ch)

没有问题!

再看有缓冲通道:

package main

import (
	"fmt"
	"time"
)

// 接收消息函数
func receiveMessage(ch <-chan string) {
	msg := <-ch
	fmt.Println("接收到消息:", msg)
}

// 发送消息函数
func sendMessage(ch chan<- string, msg string) {
	ch <- msg
	fmt.Println("发送消息:", msg)
}
func main() {
	// 创建通道
	ch := make(chan string, 1)

	// 启动接收消息的 goroutine
	sendMessage(ch, "Hello, test!")
	go receiveMessage(ch)

	// 发送消息

	// 保持程序运行,等待接收消息
	time.Sleep(3 * time.Second)

}

运行结果:

可以看出运行是没有问题的。

当有缓冲的channel内无数据继续读会发生什么
func main() {
	num := 5
	wg := sync.WaitGroup{}
	var resch = make(chan int, 100)
	for i := 0; i < num; i++ {
		wg.Add(1)
		go func(params int) {
			defer wg.Done()
			//defer close(resch)
			resch <- job(params)
			//fmt.Println(job(params))
		}(i)
	}
	//go func() {
	wg.Wait()
	//defer close(resch)
	//}()

	for v := range resch {
		fmt.Println(v)
	}
	//resch <- 1
}

看channel的容量是100,我只向里面发送5条数据,读取后不关闭,死锁

那么向一个关闭的协程写数据会发生什么呢
func main() {
	num := 5
	wg := sync.WaitGroup{}
	var resch = make(chan int, 100)
	for i := 0; i < num; i++ {
		wg.Add(1)
		go func(params int) {
			defer wg.Done()
			//defer close(resch)
			resch <- job(params)
			//fmt.Println(job(params))
		}(i)
	}
	go func() {
		wg.Wait()
		defer close(resch)
	}()

	for v := range resch {
		fmt.Println(v)
	}
	resch <- 1
}

panic!

向一个关闭的协程取呢?
func main() {
	num := 5
	wg := sync.WaitGroup{}
	var resch = make(chan int, 100)
	for i := 0; i < num; i++ {
		wg.Add(1)
		go func(params int) {
			defer wg.Done()
			//defer close(resch)
			resch <- job(params)
			//fmt.Println(job(params))
		}(i)
	}
	go func() {
		wg.Wait()
		defer close(resch)
	}()

	for v := range resch {
		fmt.Println(v)
	}
	i:= <- resch
	fmt.Println(i)
}

不报错返回channel类型的0值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值