lock.go 760 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package lock
  2. import (
  3. "sync"
  4. "sync/atomic"
  5. )
  6. type mutex struct {
  7. *sync.Mutex
  8. count int32
  9. }
  10. type HighGranularityLock struct {
  11. m map[string]*mutex
  12. l sync.Mutex
  13. }
  14. func NewHighGranularityLock() *HighGranularityLock {
  15. return &HighGranularityLock{
  16. m: make(map[string]*mutex),
  17. }
  18. }
  19. func (l *HighGranularityLock) Lock(key string) {
  20. l.l.Lock()
  21. var m *mutex
  22. var ok bool
  23. if m, ok = l.m[key]; !ok {
  24. m = &mutex{Mutex: &sync.Mutex{}, count: 1}
  25. l.m[key] = m
  26. } else {
  27. atomic.AddInt32(&m.count, 1)
  28. }
  29. l.l.Unlock()
  30. m.Lock()
  31. }
  32. func (l *HighGranularityLock) Unlock(key string) {
  33. l.l.Lock()
  34. m, ok := l.m[key]
  35. if !ok {
  36. return
  37. }
  38. atomic.AddInt32(&m.count, -1)
  39. if atomic.LoadInt32(&m.count) == 0 {
  40. delete(l.m, key)
  41. }
  42. l.l.Unlock()
  43. m.Unlock()
  44. }