feat(common): 添加无锁并发工具包依赖
新增 lockfree-1.1.3 工具包到 go.work 文件中,为项目提供无锁并发数据结构支持, 提升高并发场景下的性能表现。
This commit is contained in:
160
common/utils/lockfree-1.1.3/blocks.go
Normal file
160
common/utils/lockfree-1.1.3/blocks.go
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package lockfree
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// blockStrategy 阻塞策略
|
||||
type blockStrategy interface {
|
||||
// block 阻塞
|
||||
block(actual *uint64, expected uint64)
|
||||
|
||||
// release 释放阻塞
|
||||
release()
|
||||
}
|
||||
|
||||
// SchedBlockStrategy 调度等待策略
|
||||
// 调用runtime.Gosched()方法使当前 g 主动让出 cpu 资源。
|
||||
type SchedBlockStrategy struct {
|
||||
}
|
||||
|
||||
func (s *SchedBlockStrategy) block(actual *uint64, expected uint64) {
|
||||
runtime.Gosched()
|
||||
}
|
||||
|
||||
func (s *SchedBlockStrategy) release() {
|
||||
}
|
||||
|
||||
// SleepBlockStrategy 休眠等待策略
|
||||
// 调用 Sleep 方法使当前 g 主动让出 cpu 资源。
|
||||
// sleep poll 参考值:
|
||||
// 轮询时长为 10us 时,cpu 开销约 2-3% 左右。
|
||||
// 轮询时长为 5us 时,cpu 开销约在 10% 左右。
|
||||
// 轮询时长小于 5us 时,cpu 开销接近 100% 满载。
|
||||
type SleepBlockStrategy struct {
|
||||
t time.Duration
|
||||
}
|
||||
|
||||
func NewSleepBlockStrategy(wait time.Duration) *SleepBlockStrategy {
|
||||
return &SleepBlockStrategy{
|
||||
t: wait,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SleepBlockStrategy) block(actual *uint64, expected uint64) {
|
||||
time.Sleep(s.t)
|
||||
}
|
||||
|
||||
func (s *SleepBlockStrategy) release() {
|
||||
}
|
||||
|
||||
// ProcYieldBlockStrategy CPU空指令策略
|
||||
type ProcYieldBlockStrategy struct {
|
||||
cycle uint32
|
||||
}
|
||||
|
||||
func NewProcYieldBlockStrategy(cycle uint32) *ProcYieldBlockStrategy {
|
||||
return &ProcYieldBlockStrategy{
|
||||
cycle: cycle,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProcYieldBlockStrategy) block(actual *uint64, expected uint64) {
|
||||
procyield(s.cycle)
|
||||
}
|
||||
|
||||
func (s *ProcYieldBlockStrategy) release() {
|
||||
}
|
||||
|
||||
// OSYieldBlockStrategy 操作系统调度策略
|
||||
type OSYieldBlockStrategy struct {
|
||||
}
|
||||
|
||||
func NewOSYieldWaitStrategy() *OSYieldBlockStrategy {
|
||||
return &OSYieldBlockStrategy{}
|
||||
}
|
||||
|
||||
func (s *OSYieldBlockStrategy) block(actual *uint64, expected uint64) {
|
||||
osyield()
|
||||
}
|
||||
|
||||
func (s *OSYieldBlockStrategy) release() {
|
||||
}
|
||||
|
||||
// ChanBlockStrategy chan阻塞策略
|
||||
type ChanBlockStrategy struct {
|
||||
bc chan struct{}
|
||||
b uint32
|
||||
}
|
||||
|
||||
func NewChanBlockStrategy() *ChanBlockStrategy {
|
||||
return &ChanBlockStrategy{
|
||||
bc: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChanBlockStrategy) block(actual *uint64, expected uint64) {
|
||||
// 0:未阻塞;1:阻塞
|
||||
if atomic.CompareAndSwapUint32(&s.b, 0, 1) {
|
||||
// 设置成功的话,表示阻塞,需要进行二次判断
|
||||
if atomic.LoadUint64(actual) == expected {
|
||||
// 表示阻塞失败,因为结果是一致的,此处需要重新将状态调整回来
|
||||
if atomic.CompareAndSwapUint32(&s.b, 1, 0) {
|
||||
// 表示回调成功,直接退出即可
|
||||
return
|
||||
} else {
|
||||
// 表示有其他协程release了,则读取对应chan即可
|
||||
<-s.bc
|
||||
}
|
||||
} else {
|
||||
// 如果说结果不一致,则表示阻塞,等待被释放即可
|
||||
<-s.bc
|
||||
}
|
||||
}
|
||||
// 没有设置成功,不用关注
|
||||
}
|
||||
|
||||
func (s *ChanBlockStrategy) release() {
|
||||
if atomic.CompareAndSwapUint32(&s.b, 1, 0) {
|
||||
// 表示可以释放,即chan是等待状态
|
||||
s.bc <- struct{}{}
|
||||
}
|
||||
// 无法设置则不用关心
|
||||
return
|
||||
}
|
||||
|
||||
// ConditionBlockStrategy condition 阻塞策略
|
||||
type ConditionBlockStrategy struct {
|
||||
cond *sync.Cond
|
||||
}
|
||||
|
||||
func NewConditionBlockStrategy() *ConditionBlockStrategy {
|
||||
return &ConditionBlockStrategy{
|
||||
cond: sync.NewCond(&sync.Mutex{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConditionBlockStrategy) block(actual *uint64, expected uint64) {
|
||||
s.cond.L.Lock()
|
||||
defer s.cond.L.Unlock()
|
||||
if atomic.LoadUint64(actual) == expected {
|
||||
return
|
||||
}
|
||||
s.cond.Wait()
|
||||
}
|
||||
|
||||
func (s *ConditionBlockStrategy) release() {
|
||||
s.cond.L.Lock()
|
||||
defer s.cond.L.Unlock()
|
||||
s.cond.Broadcast()
|
||||
}
|
||||
Reference in New Issue
Block a user