返回
巧用 Go 原子操作,用好锁,告别性能低迷!##
后端
2024-02-20 08:39:55
开篇并发是业务开发中经常要面对的问题,很多时候我们会直接用一把 sync.Mutex
互斥锁来线性化处理,保证每一时刻进入临界区的 goroutine
只有一个。这样避免了并发,但性能也随着降低。
什么是原子操作
原子操作是指不可分割的操作 。在执行原子操作时,不会被其他 goroutine 中断,这意味着原子操作是线程安全的。
Go 中的原子操作
Go 中提供了原子操作包 sync/atomic
,它提供了几个内置的原子操作函数,可以用于对共享变量进行原子操作。
AddInt64
AddInt64
函数将一个 int64
类型的值添加到一个共享的 int64
类型变量中。
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var count int64 = 0
// 使用原子操作将 count 增加 1000 次
for i := 0; i < 1000; i++ {
atomic.AddInt64(&count, 1)
}
fmt.Println("最终计数:", count)
}
CompareAndSwapInt64
CompareAndSwapInt64
函数将一个共享的 int64
类型变量的值与一个给定的值进行比较,如果相等,则将该变量的值更新为另一个给定的值。
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var count int64 = 0
// 尝试将 count 的值从 0 更新为 1
success := atomic.CompareAndSwapInt64(&count, 0, 1)
if success {
fmt.Println("更新成功!")
} else {
fmt.Println("更新失败!")
}
fmt.Println("最终计数:", count)
}
atomic.Value
atomic.Value
类型提供了一种原子操作,可以存储和修改共享变量。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
// 创建一个 atomic.Value 并设置初始值
var count atomic.Value
count.Store(0)
// 使用原子操作将 count 增加 1000 次
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// 将 count 的值增加 1
count.Store(count.Load().(int) + 1)
}()
}
wg.Wait()
// 获取最终计数
finalCount := count.Load()
fmt.Println("最终计数:", finalCount)
}
结语
Go 中的原子操作是一种非常强大的工具,可以帮助我们提升并发程序的性能。在需要对共享变量进行并发操作时,我们应该优先考虑使用原子操作。