Goroutines and mutex

Issue

func (s *Server) start() {
         s.Lock()
         defer s.Unlock()
        if !s.isClosed{
           go s.processing()
        }
        go s.start()
 }

func (s *Server) processing() {
  s.Lock()
  // do stuff
  s.Unlock()
}

I have a working Golang project that has a block of code following the logic shown above.

I don’t understand why this logic works as I would’ve expected a deadlock.

Solution

We’ll call the initial goroutine that’s running when start is entered G1.

  1. start (in G1) locks the mutex and defers the unlock until start returns.
  2. start calls s.processing in a new goroutine (G2)
  3. start calls itself in a new goroutine (G3)
  4. start (G1) unlocks the mutex and returns.

None of those calls except the lock at Step 1 is a blocking call. Concurrently, in G2, s.processing waits for start to unlock the mutex (which will happen pretty quickly because all start does is start a couple goroutines before unlocking the mutex). Also concurrently, in G3, the above 4 steps are performed all over again (on an apparently infinite loop).

There is no point in that logic that could cause a deadlock.

Answered By – Adrian

Answer Checked By – Gilberto Lyons (GoLangFix Admin)

Leave a Reply

Your email address will not be published.