1 Star 0 Fork 0

余济舟/util

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
map_lock.go 3.08 KB
一键复制 编辑 原始数据 按行查看 历史
余济舟 提交于 2024-08-13 17:13 . [optimize]升级lock
package lock
import (
"fmt"
"gitee.com/jericho-yu/util/v2/dict"
"log"
"sync"
"time"
)
type (
// MapLock 字典锁:一个锁的集合
MapLock struct {
locks *dict.AnyDict[string, *itemLock]
}
// 锁项:一个集合锁中的每一项,包含:锁状态、锁值、超时时间、定时器
itemLock struct {
inUse bool
val any
timeout time.Duration
timer *time.Timer
}
)
var (
onceMapLock sync.Once
mapLockIns *MapLock
MapLockApp MapLock
)
// New 实例化:字典锁
func (MapLock) New() *MapLock {
return &MapLock{locks: dict.MakeAnyDict[string, *itemLock]()}
}
// Once 单例化:字典锁
func (MapLock) Once() *MapLock {
onceMapLock.Do(func() { mapLockIns = &MapLock{locks: dict.MakeAnyDict[string, *itemLock]()} })
return mapLockIns
}
// Set 创建锁
func (r *MapLock) Set(key string, val any) error {
_, exists := r.locks.Get(key)
if exists {
return fmt.Errorf("锁[%s]已存在", key)
} else {
r.locks.Set(key, &itemLock{val: val})
}
return nil
}
// SetMany 批量创建锁
func (r *MapLock) SetMany(items map[string]any) error {
for idx, item := range items {
err := r.Set(idx, item)
if err != nil {
r.DestroyAll()
return err
}
}
return nil
}
// Release 显式锁释放方法
func (r *itemLock) Release() {
if r.timer != nil {
r.timer.Stop()
r.timer = nil
}
r.inUse = false
}
// Destroy 删除锁
func (r *MapLock) Destroy(key string) {
if il, ok := r.locks.Get(key); ok {
il.Release()
r.locks.RemoveByKey(key) // 删除键值对,以便垃圾回收
}
}
// DestroyAll 删除所有锁
func (r *MapLock) DestroyAll() {
for key := range r.locks.All() {
r.Destroy(key)
}
}
// Lock 获取锁
func (r *MapLock) Lock(key string, timeout time.Duration) (*itemLock, error) {
if item, exists := r.locks.Get(key); !exists {
return nil, fmt.Errorf("锁[%s]不存在", key)
} else {
if item.inUse {
return nil, fmt.Errorf("锁[%s]被占用", key)
}
// 设置锁占用
item.inUse = true
// 设置超时时间
if timeout > 0 {
item.timeout = timeout
item.timer = time.AfterFunc(timeout, func() {
if il, ok := r.locks.Get(key); ok {
if il.timer != nil {
il.Release()
}
}
})
}
return item, nil
}
}
// Try 尝试获取锁
func (r *MapLock) Try(key string) error {
if item, exist := r.locks.Get(key); !exist {
return fmt.Errorf("锁[%s]不存在", key)
} else {
if item.inUse {
return fmt.Errorf("锁[%s]被占用", key)
}
return nil
}
}
func (MapLock) Demo() {
k8sLinks := map[string]any{
"k8s-a": &struct{}{},
"k8s-b": &struct{}{},
"k8s-c": &struct{}{},
}
// 获取字典锁对象
ml := MapLockApp.Once()
// 批量创建锁
storeErr := ml.SetMany(k8sLinks)
if storeErr != nil {
// 处理err
log.Fatalln(storeErr.Error())
}
// 检测锁
tryErr := ml.Try("k8s-a")
if tryErr != nil {
// 处理err
log.Fatalln(tryErr.Error())
}
// 获取锁
lock, lockErr := ml.Lock("k8s-a", time.Second*10) // 10秒业务处理不完也会过期 设置为:0则为永不过期
if lockErr != nil {
log.Fatalln(lockErr.Error())
}
defer lock.Release()
// 处理业务...
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jericho-yu/util.git
git@gitee.com:jericho-yu/util.git
jericho-yu
util
util
v2.16.1

搜索帮助