Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Explaining deadlocks with a single lock from The Little Go Book

I’m reading The Little Go Book.

Page 76 demonstrates how you can deadlock with a single lock:

var (
    lock sync.Mutex
)

func main() {
    go func() { lock.Lock() }()
    time.Sleep(time.Millisecond * 10)
    lock.Lock()
}

Running this results in a deadlock as explained by the author. However, what I don’t understand is why.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I changed the program to this:

var (
    lock sync.Mutex
)

func main() {
    go func() { lock.Lock() }()
    lock.Lock()
}

My expectation was that a deadlock would still be thrown. But it wasn’t.

Could someone explain to me what’s happening here please?

The only scenario I can think of that explains this is the following (but this is guesswork):

First example

  1. The lock is acquired in the first goroutine
  2. The call to time.Sleep() ensures the lock is acquired
  3. The main function attempts to acquire the lock resulting in a deadlock
  4. Program exits

Second example

  1. The lock is acquired in the first goroutine but this takes some time to happen (??)
  2. Since there is no delay the main function acquires the lock before the goroutine can
  3. Program exits

>Solution :

In the first example, main sleeps long enough to give the child goroutine the opportunity to start and acquire the lock. That goroutine then will merrily exit without releasing the lock.

By the time main resumes its control flow, the shared mutex is locked so the next attempt to acquire it will block forever. Since at this point main is the only routine left alive, blocking forever results in a deadlock.


In the second example, without the call to time.Sleep, main proceeds straight away to acquire the lock. This succeeds, so main goes ahead and exits. The child goroutine would then block forever, but since main is exited, the program terminates without deadlock.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading