From 792458a185d861e04eabc82849fb16c25a60923f Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Tue, 26 Jul 2022 14:19:40 +0800 Subject: [PATCH] update --- compiled_buffer/regex2_test.go | 17 +++++++++ dateconv/dateconv.go | 1 + locker/chan_source_locker.go | 41 ++++++++++++++++++++ locker/source_locker.go | 68 +++++++++++++++++++++++++++------- locker/source_locker_test.go | 31 ++++++++++++++++ 5 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 compiled_buffer/regex2_test.go create mode 100644 locker/chan_source_locker.go diff --git a/compiled_buffer/regex2_test.go b/compiled_buffer/regex2_test.go new file mode 100644 index 0000000..67c2685 --- /dev/null +++ b/compiled_buffer/regex2_test.go @@ -0,0 +1,17 @@ +package compiledbuffer + +import ( + "testing" + + "github.com/dlclark/regexp2" +) + +func TestCom(t *testing.T) { + regex, err := regexp2.Compile(`^\d{11}[;;](?!(37|38))\d{2}\d{6}$`, regexp2.None) + if err != nil { + t.Fatal(err) + } + + t.Log(regex.MatchString("14610522152;37764800")) + t.Log(regex.MatchString("14610522152;33764800")) +} diff --git a/dateconv/dateconv.go b/dateconv/dateconv.go index ea43de1..eda7d62 100644 --- a/dateconv/dateconv.go +++ b/dateconv/dateconv.go @@ -7,6 +7,7 @@ import ( const ( layoutDate = "2006-01-02" layoutTime = "2006-01-02 15:04:05" + layoutTimeMilli = "2006-01-02 15:04:05.000" layoutChineseDate = "2006年01月02日" layoutChineseTime = "2006年01月02日 15:04:05" ) diff --git a/locker/chan_source_locker.go b/locker/chan_source_locker.go new file mode 100644 index 0000000..68fe22e --- /dev/null +++ b/locker/chan_source_locker.go @@ -0,0 +1,41 @@ +package locker + +type ChanLocker interface { + Get(key string) (ch <-chan int, ok bool) + Release(key string) +} + +type chanSourceLock struct { + m RWLocker + content map[string]chan int +} + +func (s *chanSourceLock) Get(key string) (ch <-chan int, ok bool) { + s.m.RLock() + ch, ok = s.content[key] + s.m.RUnlock() + if ok { + return + } + s.m.Lock() + ch, ok = s.content[key] + if ok { + s.m.Unlock() + return + } + s.content[key] = make(chan int) + ch = s.content[key] + ok = true + s.m.Unlock() + return +} + +func (s *chanSourceLock) Release(key string) { + s.m.Lock() + ch, ok := s.content[key] + if ok { + close(ch) + delete(s.content, key) + } + s.m.Unlock() +} diff --git a/locker/source_locker.go b/locker/source_locker.go index 34bc0a3..be5eda0 100644 --- a/locker/source_locker.go +++ b/locker/source_locker.go @@ -2,53 +2,93 @@ package locker import ( "fmt" + "sync/atomic" ) +// 带计数器锁 +type countLocker struct { + Locker + Count int32 +} + // 资源锁 type SourceLocker struct { m RWLocker - locks map[string]Locker + locks map[string]*countLocker } func NewSourceLocker() *SourceLocker { return &SourceLocker{ m: NewRWLocker(), - locks: make(map[string]Locker), + locks: make(map[string]*countLocker), } } func (s *SourceLocker) Lock(key string) { s.m.RLock() l, ok := s.locks[key] + s.m.RUnlock() if ok { - s.m.RUnlock() - + atomic.AddInt32(&l.Count, 1) l.Lock() + fmt.Println("加锁") } else { - s.m.RUnlock() - + // 加锁,再次检查是否已经具有锁 s.m.Lock() - new := NewLocker() - s.locks[key] = new - s.m.Unlock() + if l2, ok := s.locks[key]; ok { + s.m.Unlock() - new.Lock() - fmt.Println("初始加锁") + l2.Lock() + fmt.Println("二次检查加锁") + } else { + new := NewLocker() + s.locks[key] = &countLocker{Locker: new, Count: 1} + + s.m.Unlock() + + fmt.Printf("新锁准备加锁:%p\n", new) + new.Lock() + + fmt.Println("初始加锁") + } } } func (s *SourceLocker) Unlock(key string) { s.m.Lock() + if l, ok := s.locks[key]; ok { + atomic.AddInt32(&l.Count, -1) + fmt.Printf("解锁%p\n", l) l.Unlock() - // delete(s.locks, key) - fmt.Println("解锁") + + if l.Count == 0 { + delete(s.locks, key) + } } s.m.Unlock() } func (s *SourceLocker) TryLock(key string) bool { - return false + // 加读锁 + s.m.RLock() + l, ok := s.locks[key] + + if ok { + ret := l.TryLock() + s.m.RUnlock() + + return ret + } else { + s.m.RUnlock() + + s.m.Lock() + new := NewLocker() + s.locks[key] = &countLocker{Locker: new, Count: 1} + s.m.Unlock() + + return new.TryLock() + } } diff --git a/locker/source_locker_test.go b/locker/source_locker_test.go index e0674c5..dd080a0 100644 --- a/locker/source_locker_test.go +++ b/locker/source_locker_test.go @@ -3,10 +3,15 @@ package locker import ( "sync" "testing" + "time" ) var sourcekey = "u-0001" +func TestTryLock(t *testing.T) { + +} + func TestSourceLocker(t *testing.T) { l := NewSourceLocker() @@ -27,6 +32,32 @@ func TestSourceLocker(t *testing.T) { wg.Wait() t.Log("n:", n) + t.Logf("%+v", l) +} + +func TestSourceTryLock(t *testing.T) { + c := 5 + n := 0 + wg := new(sync.WaitGroup) + wg.Add(c) + + l := NewSourceLocker() + + for i := 0; i < c; i++ { + go func() { + defer wg.Done() + if l.TryLock(sourcekey) { + n++ + time.Sleep(time.Second) + + l.Unlock(sourcekey) + } + }() + } + + wg.Wait() + t.Log("n:", n) + t.Logf("%+v", l) } func BenchmarkSourceLocker(b *testing.B) {