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.
We'll call the initial goroutine that's running when start
is entered G1.
start
(in G1) locks the mutex and defers the unlock until start
returns.start
calls s.processing
in a new goroutine (G2)start
calls itself in a new goroutine (G3)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.