如何实现原子加法但不超过x



我想在纯原子操作中实现下面的add

var num int
func add(max int) int {
if num < max {
num++
}
return num
}

我试过一个版本的

func add(max int64) int64 {
for {
old := atomic.LoadInt64(&x)
if old + 1 < max {
if atomic.CompareAndSwapInt64(&x, old, old+1) {
return old+1
}
} else {
return old
}
}
}

然而,我想可能有一个更好的解决方案,更少的失败机会,避免死循环

以下是经过多goroutine测试的算法的修订版本。无论有没有围棋比赛检测器,它都能通过测试。

add.go:

package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
var x int64 = -42
func add(max int64) int64 {
for {
old := atomic.LoadInt64(&x)
if old >= max {
return old
}
new := old + 1
if atomic.CompareAndSwapInt64(&x, old, new) {
return new
}
}
}
func main() {
const max = 123456
fmt.Println("max:", max)
fmt.Println("x:  ", x)
var wg sync.WaitGroup
procs := runtime.GOMAXPROCS(0)
for i := 0; i < procs; i++ {
wg.Add(1)
go func(max int64) {
defer wg.Done()
for {
if add(max) >= max {
return
}
}
}(max)
}
wg.Wait()
fmt.Println("x:  ", x)
}

https://go.dev/play/p/r-qsnyI7tqv

$ go build -race add.go && ./add
max: 123456
x:   -42
x:   123456
$ go build add.go && ./add
max: 123456
x:   -42
x:   123456

最简单的(但不是最有效的(解决方案是使用互斥:

var (
mu  sync.Mutex
num int64
)
func add(max int64) int64 {
mu.Lock()
defer mu.Unlock()
if num < max {
num++
}
return num
}

相关内容

  • 没有找到相关文章

最新更新