lock.go 904 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package lock
  2. import (
  3. "sync"
  4. "sync/atomic"
  5. )
  6. type mutex struct {
  7. *sync.Mutex
  8. count int32
  9. }
  10. type GranularityLock struct {
  11. m map[string]*mutex
  12. l sync.Mutex
  13. }
  14. func NewGranularityLock() *GranularityLock {
  15. return &GranularityLock{
  16. m: make(map[string]*mutex),
  17. }
  18. }
  19. func (l *GranularityLock) 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 *GranularityLock) TryLock(key string) bool {
  33. l.l.Lock()
  34. m, ok := l.m[key]
  35. if !ok {
  36. return false
  37. }
  38. locked := m.TryLock()
  39. l.l.Unlock()
  40. return locked
  41. }
  42. func (l *GranularityLock) Unlock(key string) {
  43. l.l.Lock()
  44. m, ok := l.m[key]
  45. if !ok {
  46. return
  47. }
  48. atomic.AddInt32(&m.count, -1)
  49. if atomic.LoadInt32(&m.count) == 0 {
  50. delete(l.m, key)
  51. }
  52. l.l.Unlock()
  53. m.Unlock()
  54. }