MikeZhang
MikeZhang

Reputation: 337

Why this Go program not enter deadlock status as expected?

I am a newbie in Go, i wrote this code and hope it will enter deadlock status, but failed.

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

As you can see. this code run well and print something and then quit without any deadlock error. For I know, the first go func(){} goroutine has returned and locked the mux then quit. But the other two goroutines will be blocked because the mux has already blocked.

The function runtime.Gosched() should push the main goroutine to the only FIFO queue(runtime.GOMAXPROCS(1)) right? why it can be excute before the left two goroutine that already in the queue?

BTW,this following code will return the deadlock error as expected

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()
}

Thanks!

Upvotes: 0

Views: 416

Answers (2)

Ankur
Ankur

Reputation: 33637

A deadlock is a condition where all the goroutines are in waiting state (waiting for lock or reading from channel etc). The reason is simple, if all of them are waiting then there is no one left that can do something that lead to any of the waiting goroutines to continue. In your case your main function, which is also a goroutine is not in waiting state. When the main goroutine exits the process exits too.

The function runtime.Gosched() should push the main goroutine to the only FIFO queue(runtime.GOMAXPROCS(1)) right? why it can be excute before the left two goroutine that already in the queue?

The queue is a schedule queue. The runtime will pick a goroutine from the queue, run it for some time, pause it, pick another goroutine.

Upvotes: 2

BlackMamba
BlackMamba

Reputation: 10254

For your code:

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()
}

There is no deadlock, for

func (m *Mutex) Lock()

Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available.

So the second and third goroutine just wait there. This is busy waiting. then the main goroutine exit, so the second and third goroutine also exist.

Upvotes: 1

Related Questions