Documentation ¶
Index ¶
- type Cond
- type LimitPool
- type Map
- func (m *Map[K, V]) Delete(key K)
- func (m *Map[K, V]) Load(key K) (value V, ok bool)
- func (m *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool)
- func (m *Map[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool)
- func (m *Map[K, V]) LoadOrStoreFunc(key K, fn func() (V, error)) (actual V, loaded bool, err error)
- func (m *Map[K, V]) Range(f func(key K, value V) bool)
- func (m *Map[K, V]) Store(key K, value V)
- type Pool
- type SegmentKeysLock
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cond ¶ added in v0.0.8
Cond 实现了一个条件变量,是等待或宣布一个事件发生的goroutines的汇合点。
在改变条件和调用Wait方法的时候,Cond 关联的锁对象 L (*Mutex 或者 *RWMutex)必须被加锁,
在Go内存模型的术语中,Cond 保证 Broadcast或Signal的调用 同步于 因此而解除阻塞的 Wait 之前。
绝大多数简单用例, 最好使用 channels 而不是 Cond (Broadcast 对应于关闭一个 channel, Signal 对应于给一个 channel 发送消息).
func (*Cond) Broadcast ¶ added in v0.0.8
func (c *Cond) Broadcast()
Broadcast 唤醒所有等待在 c 上的goroutine.
调用时,caller 可以持有也可以不持有 c.L 锁
func (*Cond) Signal ¶ added in v0.0.8
func (c *Cond) Signal()
Signal 唤醒一个等待在 c 上的goroutine.
调用时,caller 可以持有也可以不持有 c.L 锁
Signal() 不影响 goroutine 调度的优先级; 如果其它的 goroutines 尝试着锁定 c.L, 它们可能在 "waiting" goroutine 之前被唤醒.
func (*Cond) Wait ¶ added in v0.0.8
Wait 自动解锁 c.L 并挂起当前调用的 goroutine. 在恢复执行之后 Wait 在返回前将加 c.L 锁成功. 和其它系统不一样, 除非调用 Broadcast 或 Signal 或者 ctx 超时了,否则 Wait 不会返回.
成功唤醒时, 返回 nil. 超时失败时, 返回ctx.Err(). 如果 ctx 超时了, Wait 可能依旧执行成功返回 nil.
在 Wait 第一次继续执行时,因为 c.L 没有加锁, 当 Wait 返回的时候,调用者通常不能假设条件是真的 相反, caller 应该在循环中调用 Wait:
c.L.Lock() for !condition() { if err := c.Wait(ctx); err != nil { // 超时唤醒了,并不是被正常唤醒的,可以做一些超时的处理 } } ... condition 满足了,do work ... c.L.Unlock()
type LimitPool ¶ added in v0.0.9
type LimitPool[T any] struct { // contains filtered or unexported fields }
LimitPool 是对 Pool 的简单封装允许用户通过控制一段时间内对Pool的令牌申请次数来间接控制Pool中对象的内存总占用量
func NewLimitPool ¶ added in v0.0.9
NewLimitPool 创建一个 LimitPool 实例 maxTokens 表示一段时间内的允许发放的最大令牌数 factory 必须返回 T 类型的值,并且不能返回 nil
Example ¶
package main import ( "fmt" "github.com/ecodeclub/ekit/syncx" ) func main() { p := syncx.NewLimitPool(1, func() int { return 123 }) val, ok := p.Get() fmt.Println("第一次", val, ok) val, ok = p.Get() fmt.Println("第二次", val, ok) p.Put(123) val, ok = p.Get() fmt.Println("第三次", val, ok) }
Output: 第一次 123 true 第二次 0 false 第三次 123 true
type Map ¶
type Map[K comparable, V any] struct { // contains filtered or unexported fields }
Map 是对 sync.Map 的一个泛型封装 要注意,K 必须是 comparable 的,并且谨慎使用指针作为 K。 使用指针的情况下,两个 key 是否相等,仅仅取决于它们的地址 而不是地址指向的值。可以参考 Load 测试。 注意,key 不存在和 key 存在但是值恰好为零值(如 nil),是两码事
func (*Map[K, V]) Delete ¶
func (m *Map[K, V]) Delete(key K)
Delete 删除键值对
Example ¶
var m Map[string, int] m.Store("key1", 123) val, ok := m.Load("key1") if ok { fmt.Printf("key1 = %d\n", val) } m.Delete("key1") _, ok = m.Load("key1") if !ok { fmt.Println("key1 已被删") }
Output: key1 = 123 key1 已被删
func (*Map[K, V]) Load ¶
Load 加载键值对
Example ¶
var m Map[string, int] m.Store("key1", 123) val, ok := m.Load("key1") if ok { fmt.Println(val) }
Output: 123
func (*Map[K, V]) LoadAndDelete ¶
LoadAndDelete 加载并且删除一个键值对
Example ¶
var m = Map[string, *User]{} _, loaded := m.LoadAndDelete("Tom") fmt.Println(loaded) m.Store("Tom", nil) val, loaded := m.LoadAndDelete("Tom") if loaded { fmt.Printf("key=Tom, val=%v 被删除\n", val) } m.Store("Tom", &User{Name: "Tom"}) val, loaded = m.LoadAndDelete("Tom") if loaded { fmt.Printf("key=Tom, val=%v 被删除\n", val) }
Output: false key=Tom, val=<nil> 被删除 key=Tom, val=&{Tom} 被删除
func (*Map[K, V]) LoadOrStore ¶
LoadOrStore 加载或者存储一个键值对 true 代表是加载的,false 代表执行了 store
Example ¶
var m = Map[string, *User]{} _, loaded := m.LoadOrStore("Tom", &User{Name: "Tom"}) // 执行存储 if !loaded { fmt.Println("设置了新值 Tom") } _, loaded = m.LoadOrStore("Tom", &User{Name: "Tom-copy"}) // Tom 这个 key 已经存在,执行加载 if loaded { fmt.Println("加载旧值 Tom") } _, loaded = m.LoadOrStore("Jerry", nil) // 执行存储,注意值是 nil if !loaded { fmt.Println("设置了新值 nil") } val, loaded := m.LoadOrStore("Jerry", &User{Name: "Jerry"}) // Jerry 这个 key 已经存在,执行加载,于是把原本的 nil 加载出来 if loaded { fmt.Printf("加载旧值 %v", val) }
Output: 设置了新值 Tom 加载旧值 Tom 设置了新值 nil 加载旧值 <nil>
func (*Map[K, V]) LoadOrStoreFunc ¶ added in v0.0.8
LoadOrStoreFunc 是一个优化,也就是使用该方法能够避免无意义的创建实例。 如果你的初始化过程非常消耗资源,那么使用这个方法是有价值的。 它的代价就是 Key 不存在的时候会多一次 Load 调用。 当 fn 返回 error 的时候,LoadOrStoreFunc 也会返回 error。
Example ¶
var m = Map[string, *User]{} _, loaded, _ := m.LoadOrStoreFunc("Tom", func() (*User, error) { return &User{Name: "Tom"}, nil }) // 执行存储 if !loaded { fmt.Println("设置了新值 Tom") } _, loaded, _ = m.LoadOrStoreFunc("Tom", func() (*User, error) { return &User{Name: "Tom-copy"}, nil }) // Tom 这个 key 已经存在,执行加载 if loaded { fmt.Println("加载旧值 Tom") } _, loaded, _ = m.LoadOrStoreFunc("Jerry", func() (*User, error) { return nil, nil }) // 执行存储,注意值是 nil if !loaded { fmt.Println("设置了新值 nil") } val, loaded, _ := m.LoadOrStoreFunc("Jerry", func() (*User, error) { return &User{Name: "Jerry"}, nil }) // Jerry 这个 key 已经存在,执行加载,于是把原本的 nil 加载出来 if loaded { fmt.Printf("加载旧值 %v\n", val) } _, _, err := m.LoadOrStoreFunc("Kitty", func() (*User, error) { return nil, errors.New("初始化失败") }) if err != nil { fmt.Println(err.Error()) }
Output: 设置了新值 Tom 加载旧值 Tom 设置了新值 nil 加载旧值 <nil> 初始化失败
type Pool ¶
type Pool[T any] struct { // contains filtered or unexported fields }
Pool 是对 sync.Pool 的简单封装 会有一些性能损耗,但是基本可以忽略不计。担忧性能问题的可以参考
type SegmentKeysLock ¶ added in v0.0.9
type SegmentKeysLock struct {
// contains filtered or unexported fields
}
SegmentKeysLock 部分key lock结构定义
func NewSegmentKeysLock ¶ added in v0.0.9
func NewSegmentKeysLock(size uint32) *SegmentKeysLock
NewSegmentKeysLock 创建 SegmentKeysLock 示例
Example ¶
package main import ( "fmt" "github.com/ecodeclub/ekit/syncx" ) func main() { // 参数就是分多少段,你也可以理解为总共有多少锁 // 锁越多,并发竞争越低,但是消耗内存; // 锁越少,并发竞争越高,但是内存消耗少; lock := syncx.NewSegmentKeysLock(100) // 对应的还有 TryLock // RLock 和 RUnlock lock.Lock("key1") defer lock.Unlock("key1") fmt.Println("OK") }
Output: OK
func (*SegmentKeysLock) RLock ¶ added in v0.0.9
func (s *SegmentKeysLock) RLock(key string)
RLock 读锁加锁
func (*SegmentKeysLock) RUnlock ¶ added in v0.0.9
func (s *SegmentKeysLock) RUnlock(key string)
RUnlock 读锁解锁
func (*SegmentKeysLock) TryLock ¶ added in v0.0.9
func (s *SegmentKeysLock) TryLock(key string) bool
TryLock 试着加锁,加锁成功会返回 true
func (*SegmentKeysLock) TryRLock ¶ added in v0.0.9
func (s *SegmentKeysLock) TryRLock(key string) bool
TryRLock 试着加读锁,加锁成功会返回
func (*SegmentKeysLock) Unlock ¶ added in v0.0.9
func (s *SegmentKeysLock) Unlock(key string)
Unlock 写锁解锁