答案:sync/atomic提供原子操作解决并发下共享变量一致性问题,核心操作包括Add、Load、Store和CompareAndSwap,适用于计数器、状态标志、配置更新等场景,相比Mutex性能更高、开销更小,但仅限于基本类型和指针操作,复杂结构需结合atomic.Value使用,且需注意复合操作非原子、内存对齐等问题。

Golang的
sync/atomic
sync.Mutex
在并发编程中,当我们有多个goroutine同时读写同一个变量时,如果不加保护,就会出现数据竞态(race condition),导致结果不可预测。
sync/atomic
sync.Mutex
sync/atomic
sync/atomic
int32
int64
uint32
uint64
unsafe.Pointer
AddInt32/AddInt64
立即学习“go语言免费学习笔记(深入)”;
++
++
import "sync/atomic"
var requestCount int64
func handleRequest() { // 处理请求... atomic.AddInt64(&requestCount, 1) // 原子地增加计数 }
LoadInt32/LoadInt64/LoadPointer
import "sync/atomic"
var configVersion int32 var currentConfig atomic.Value // 存储配置结构体
func getConfig() interface{} { return currentConfig.Load() // 原子地加载最新的配置 }
func updateConfig(newConfig interface{}) { currentConfig.Store(newConfig) // 原子地存储新配置 atomic.AddInt32(&configVersion, 1) }
这里顺便提到了`atomic.Value`,它能原子地存储和加载任意类型的值,非常适合那些需要频繁读取但更新不那么频繁的配置或数据结构。
StoreInt32/StoreInt64/StorePointer
import "sync/atomic"
var isReady int32 // 0表示未就绪,1表示已就绪
func setReady() { atomic.StoreInt32(&isReady, 1) // 原子地设置状态 }
CompareAndSwapInt32/CompareAndSwapInt64/CompareAndSwapPointer
import "sync/atomic"
var initialized uint32 // 0表示未初始化,1表示已初始化
func initializeOnce() { if atomic.CompareAndSwapUint32(&initialized, 0, 1) { // 只有当initialized为0时,才将其设置为1,并执行初始化逻辑 // 这段代码块只会执行一次 println("Performing one-time initialization...") // 实际的初始化代码... } }
CAS操作的强大之处在于它提供了一种“乐观”的并发控制策略:先尝试,如果发现有人抢先了,那就再试一次或者放弃。这在很多场景下比悲观锁(Mutex)效率更高。
sync/atomic
这是一个非常好的问题,也是很多初学者容易混淆的地方。我的看法是,
sync/atomic
sync.Mutex
sync.Mutex
而
sync/atomic
LOCK
atomic
atomic
当然,
sync/atomic
map
slice
atomic
sync.Mutex
总结来说,如果你的并发操作只是针对单个、简单的值进行读、写、加、减或比较交换,并且对性能有较高要求,那么
sync/atomic
sync.Mutex
sync.RWMutex
sync/atomic
处理复杂数据结构时,
sync/atomic
atomic.Value
sync/atomic
1. 高性能计数器: 对于简单的计数,
atomic.AddInt64
import (
"sync/atomic"
"time"
)
// HighPerformanceCounter 是一个高性能的并发计数器
type HighPerformanceCounter struct {
value int64
}
// Increment 原子地增加计数
func (c *HighPerformanceCounter) Increment() {
atomic.AddInt64(&c.value, 1)
}
// Get 获取当前计数
func (c *HighPerformanceCounter) Get() int64 {
return atomic.LoadInt64(&c.value)
}
// Reset 重置计数
func (c *HighPerformanceCounter) Reset() {
// 使用CAS来重置,确保在并发重置时只有一个成功
for {
oldVal := atomic.LoadInt64(&c.value)
if atomic.CompareAndSwapInt64(&c.value, oldVal, 0) {
break
}
// 如果CAS失败,说明有其他goroutine修改了值,重试
time.Sleep(1 * time.Microsecond) // 稍微等待,避免忙循环
}
}
// 示例用法
// var myCounter HighPerformanceCounter
// myCounter.Increment()
// count := myCounter.Get()
// myCounter.Reset()这里,
Reset
StoreInt64(0)
StoreInt64(0)
2. 复杂数据结构的原子更新:atomic.Value
map
slice
sync/atomic
atomic.Value
interface{}Store
import (
"fmt"
"sync/atomic"
"time"
)
// Config 是一个示例配置结构体
type Config struct {
Endpoint string
Timeout time.Duration
// 更多配置项...
}
var globalConfig atomic.Value // 存储 *Config 类型
func init() {
// 初始化时存储一个默认配置
globalConfig.Store(&Config{
Endpoint: "default.api.com",
Timeout: 5 * time.Second,
})
}
// GetCurrentConfig 获取当前配置
func GetCurrentConfig() *Config {
return globalConfig.Load().(*Config) // 原子地加载并类型断言
}
// UpdateGlobalConfig 更新全局配置
func UpdateGlobalConfig(newEndpoint string, newTimeout time.Duration) {
// 创建一个新的Config实例,因为Config是不可变的
newConfig := &Config{
Endpoint: newEndpoint,
Timeout: newTimeout,
}
globalConfig.Store(newConfig) // 原子地替换旧配置
fmt.Printf("配置已更新为: %+v\n", newConfig)
}
func main() {
// 多个goroutine可以并发读取配置
go func() {
for {
cfg := GetCurrentConfig()
fmt.Printf("Goroutine 1 正在使用配置: %+v\n", cfg)
time.Sleep(1 * time.Second)
}
}()
go func() {
for {
cfg := GetCurrentConfig()
fmt.Printf("Goroutine 2 正在使用配置: %+v\n", cfg)
time.Sleep(1500 * time.Millisecond)
}
}()
// 模拟配置更新
time.Sleep(3 * time.Second)
UpdateGlobalConfig("new.api.com", 10*time.Second)
time.Sleep(5 * time.Second)
UpdateGlobalConfig("another.api.com", 2*time.Second)
select {} // 保持主goroutine运行
}这里面的核心思想是“写时复制”(Copy-on-Write)。每次更新配置,我们不是修改原有的
Config
Config
atomic.Value
Store
3. 陷阱与注意事项:
atomic
atomic
Load
Store
sync.Mutex
int64
uint64
int64
unsafe.Pointer
atomic.Pointer
unsafe.Pointer
atomic.Value
atomic
atomic
sync.Mutex
sync.WaitGroup
sync.Cond
channel
总的来说,
sync/atomic
sync.Mutex
以上就是Golang sync/atomic库原子操作及应用实例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号