Prompt
Follow these critical patterns when using locks to prevent deadlocks, resource leaks, and performance issues:
- Use consistent lock naming:
// Prefer taskTrackerLock sync.RWMutex // Over taskTrackerMu sync.RWMutex - Never perform I/O or long-running operations while holding a lock: ```go // Bad func (s *Service) ProcessData() { s.lock.Lock() defer s.lock.Unlock() response := s.client.Call() // I/O operation! // … }
// Good func (s *Service) ProcessData() { response := s.client.Call() // Do I/O first
s.lock.Lock()
defer s.lock.Unlock()
// Only use lock for quick state updates } ```
- Always clean up timers properly to prevent goroutine leaks:
if !timer.Stop() { select { case <-timer.C: // drain the channel if fired default: } } - Use timeouts and context propagation to prevent indefinite lock holding: ```go ctx, cancel := context.WithTimeout(ctx, taskTimeout) defer cancel()
s.lock.Lock() defer s.lock.Unlock()
select { case <-ctx.Done(): return ctx.Err() case <-s.workChan: // Process work } ```