mirror of
https://github.com/charlienet/go-mixed.git
synced 2025-07-18 00:22:41 +08:00
update
This commit is contained in:
17
compiled_buffer/regex2_test.go
Normal file
17
compiled_buffer/regex2_test.go
Normal file
@ -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"))
|
||||||
|
}
|
@ -7,6 +7,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
layoutDate = "2006-01-02"
|
layoutDate = "2006-01-02"
|
||||||
layoutTime = "2006-01-02 15:04:05"
|
layoutTime = "2006-01-02 15:04:05"
|
||||||
|
layoutTimeMilli = "2006-01-02 15:04:05.000"
|
||||||
layoutChineseDate = "2006年01月02日"
|
layoutChineseDate = "2006年01月02日"
|
||||||
layoutChineseTime = "2006年01月02日 15:04:05"
|
layoutChineseTime = "2006年01月02日 15:04:05"
|
||||||
)
|
)
|
||||||
|
41
locker/chan_source_locker.go
Normal file
41
locker/chan_source_locker.go
Normal file
@ -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()
|
||||||
|
}
|
@ -2,53 +2,93 @@ package locker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 带计数器锁
|
||||||
|
type countLocker struct {
|
||||||
|
Locker
|
||||||
|
Count int32
|
||||||
|
}
|
||||||
|
|
||||||
// 资源锁
|
// 资源锁
|
||||||
type SourceLocker struct {
|
type SourceLocker struct {
|
||||||
m RWLocker
|
m RWLocker
|
||||||
locks map[string]Locker
|
locks map[string]*countLocker
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSourceLocker() *SourceLocker {
|
func NewSourceLocker() *SourceLocker {
|
||||||
return &SourceLocker{
|
return &SourceLocker{
|
||||||
m: NewRWLocker(),
|
m: NewRWLocker(),
|
||||||
locks: make(map[string]Locker),
|
locks: make(map[string]*countLocker),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SourceLocker) Lock(key string) {
|
func (s *SourceLocker) Lock(key string) {
|
||||||
s.m.RLock()
|
s.m.RLock()
|
||||||
l, ok := s.locks[key]
|
l, ok := s.locks[key]
|
||||||
|
s.m.RUnlock()
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
s.m.RUnlock()
|
atomic.AddInt32(&l.Count, 1)
|
||||||
|
|
||||||
l.Lock()
|
l.Lock()
|
||||||
|
|
||||||
fmt.Println("加锁")
|
fmt.Println("加锁")
|
||||||
} else {
|
} else {
|
||||||
s.m.RUnlock()
|
// 加锁,再次检查是否已经具有锁
|
||||||
|
|
||||||
s.m.Lock()
|
s.m.Lock()
|
||||||
new := NewLocker()
|
if l2, ok := s.locks[key]; ok {
|
||||||
s.locks[key] = new
|
s.m.Unlock()
|
||||||
s.m.Unlock()
|
|
||||||
|
|
||||||
new.Lock()
|
l2.Lock()
|
||||||
fmt.Println("初始加锁")
|
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) {
|
func (s *SourceLocker) Unlock(key string) {
|
||||||
s.m.Lock()
|
s.m.Lock()
|
||||||
|
|
||||||
if l, ok := s.locks[key]; ok {
|
if l, ok := s.locks[key]; ok {
|
||||||
|
atomic.AddInt32(&l.Count, -1)
|
||||||
|
fmt.Printf("解锁%p\n", l)
|
||||||
l.Unlock()
|
l.Unlock()
|
||||||
// delete(s.locks, key)
|
|
||||||
fmt.Println("解锁")
|
if l.Count == 0 {
|
||||||
|
delete(s.locks, key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.m.Unlock()
|
s.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SourceLocker) TryLock(key string) bool {
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,15 @@ package locker
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sourcekey = "u-0001"
|
var sourcekey = "u-0001"
|
||||||
|
|
||||||
|
func TestTryLock(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestSourceLocker(t *testing.T) {
|
func TestSourceLocker(t *testing.T) {
|
||||||
l := NewSourceLocker()
|
l := NewSourceLocker()
|
||||||
|
|
||||||
@ -27,6 +32,32 @@ func TestSourceLocker(t *testing.T) {
|
|||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
t.Log("n:", n)
|
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) {
|
func BenchmarkSourceLocker(b *testing.B) {
|
||||||
|
Reference in New Issue
Block a user