请教一个协程死锁的问题
type goWorker struct {
// task is a job should be done.
task chan func()
}
func main() {
myf:=func(){
fmt.Println("aaa")
}
m:=&goWorker{
task:make(chan func()),
}
go func(){
m.task<-myf
}()
for f:=range m.task{
if f==nil{
return
}
f()
}
aa:
for{
goto aa
}
}
以上代码输出aaa后马上报死锁,这我可以理解的,除非在m.task<-myf后加一句close(m.task)才不会死锁,但是如果改一下代码,把chan读写换一下位置:
type goWorker struct {
// task is a job should be done.
task chan func()
}
func main() {
myf:=func(){
fmt.Println("aaa")
}
m:=&goWorker{
task:make(chan func()),
}
go func(){
for f:=range m.task{
if f==nil{
return
}
f()
}
}()
m.task<-myf
aa:
for{
goto aa
}
}
这样程序就正常了,不会死锁,但是我无法理解,为什么这情的写法不会死锁,我也没有close chan 啊,难道在主协程写chan,新开的协程里读取就不死锁,反过来就不行?请教一下怎么回事?是什么原理。
// task is a job should be done.
task chan func()
}
func main() {
myf:=func(){
fmt.Println("aaa")
}
m:=&goWorker{
task:make(chan func()),
}
go func(){
m.task<-myf
}()
for f:=range m.task{
if f==nil{
return
}
f()
}
aa:
for{
goto aa
}
}
以上代码输出aaa后马上报死锁,这我可以理解的,除非在m.task<-myf后加一句close(m.task)才不会死锁,但是如果改一下代码,把chan读写换一下位置:
type goWorker struct {
// task is a job should be done.
task chan func()
}
func main() {
myf:=func(){
fmt.Println("aaa")
}
m:=&goWorker{
task:make(chan func()),
}
go func(){
for f:=range m.task{
if f==nil{
return
}
f()
}
}()
m.task<-myf
aa:
for{
goto aa
}
}
这样程序就正常了,不会死锁,但是我无法理解,为什么这情的写法不会死锁,我也没有close chan 啊,难道在主协程写chan,新开的协程里读取就不死锁,反过来就不行?请教一下怎么回事?是什么原理。
...全文
相关推荐
关于Golang使用channel的死锁问题
"本文主要讨论了在Golang中使用channel时遇到的死锁问题,分析了死锁产生的原因,并提供了一个简单的代码示例来展示这种问题。"在Golang中,channel是实现协程间同步和通信的关键
go代码-go 协程保活机制
本文将深入探讨Go协程的工作原理以及如何确保它们能够在预期的时间内正常运行。首先,让我们了解什么是协程保活。在多协程环境中,有时一个或多个协程可能会因为某些原因陷入死锁、阻塞或无限制地等待资源。
详细介绍 进程、线程和协程的区别
由于线程共享内存,它们可以高效地进行数据交换,但这也带来了竞态条件和死锁等问题,需要同步机制来解决。相比于进程,线程创建和销毁的开销较小,因此在多核系统中,线程更常用于实现并发执行。3.
amareya java 协程
对于那些需要高效并发处理的项目,尤其是I/O密集型任务,使用Amareya协程库是一个值得考虑的选项。然而,理解并熟练掌握协程的原理和使用方式至关重要,这样才能充分利用其优势,避免潜在的问题。
c++ 2017 协程
协程的使用通常适用于那些需要处理大量异步任务的场景,比如网络服务、任务调度等。通过使用协程,开发者可以编写更清晰、更高效的并发代码,而无需担心传统多线程编程中遇到的问题,比如锁竞争和死锁。


