我是Go的新手,我写了这段代码并希望它会进入死锁状态,但失败了。
var mux sync.Mutex
func main() {
runtime.GOMAXPROCS(1)
for i := 0; i < 3; i++ {
go func() {
log.Println("Trying to Lock the Mux")
mux.Lock()
log.Println("The mux is Locked")
}()
}
runtime.Gosched()
}
//Output:
//2017/01/17 08:59:42 Trying to Lock the Mux
//2017/01/17 08:59:42 The mux is Locked
//2017/01/17 08:59:42 Trying to Lock the Mux
//2017/01/17 08:59:42 Trying to Lock the Mux
如你所见。这段代码运行良好并打印一些东西然后退出而没有任何死锁错误。我知道,第一个去func(){} goroutine已经返回并锁定了多路复用器然后退出。但其他两个goroutines将被阻止,因为多路复用器已经被阻止。
函数 runtime.Gosched()应该将主goroutine推送到唯一的FIFO队列( runtime.GOMAXPROCS(1))吗?为什么它可以在已经在队列中的左两个goroutine之前执行?
顺便说一句,以下代码将按预期返回死锁错误
var mux sync.Mutex
func main() {
runtime.GOMAXPROCS(1)
var wg sync.WaitGroup
wg.Add(3)
for i := 0; i < 3; i++ {
go func() {
defer wg.Done()
log.Println("Trying to Lock the Mux")
mux.Lock()
log.Println("The mux is Locked")
}()
}
wg.Wait()
}
谢谢!
答案 0 :(得分:2)
死锁是一种情况,其中所有 goroutines处于等待状态(等待锁定或从通道读取等)。原因很简单,如果他们所有人都在等待那么就没有人可以做任何导致任何等待的goroutine继续下去的事情。在您的情况下,您的主要功能,也是一个goroutine不处于等待状态。当主要的goroutine退出进程时也会退出。
函数runtime.Gosched()应该将主goroutine推送到 只有FIFO队列(runtime.GOMAXPROCS(1))对吗?为什么它可以执行 在已经在队列中的左两个goroutine之前?
队列是一个计划队列。运行时将从队列中选择一个goroutine,运行一段时间,暂停它,选择另一个goroutine。
答案 1 :(得分:1)
代码:
var mux sync.Mutex
func main() {
runtime.GOMAXPROCS(1)
for i := 0; i < 3; i++ {
go func() {
log.Println("Trying to Lock the Mux")
mux.Lock()
log.Println("The mux is Locked")
}()
}
runtime.Gosched()
}
没有死锁
func(m * Mutex)Lock()
锁定锁。如果锁已被使用, 调用goroutine阻塞,直到互斥锁可用。
所以第二和第三个goroutine就在那里等待。这是busy waiting。然后是主要的goroutine出口,所以第二和第三个goroutine也存在。