本文介绍: atomic 包是 Go 语言中用于进行原子操作的标准库。原子操作是一种在多线程并发编程中用来确保数据安全的机制,它可以防止多个线程同时访问同一个资源而导致的数据竞争问题。atomic 包中的函数是原子操作,它们在执行时不会被中断,从而确保操作的不可分割性。这对于执行复杂的操作,如比较并交换,是非常重要的。在某些情况下,使用互斥锁来保护共享变量可能会导致额外的锁开销和上下文切换,从而影响性能。atomic 包的原子操作不需要使用锁,可以减少这些开销。
作用与优势
atomic 包是 Go 语言中用于进行原子操作的标准库。原子操作是一种在多线程并发编程中用来确保数据安全的机制,它可以防止多个线程同时访问同一个资源而导致的数据竞争问题。
atomic 包中的函数是原子操作,它们在执行时不会被中断,从而确保操作的不可分割性。这对于执行复杂的操作,如比较并交换,是非常重要的。
在某些情况下,使用互斥锁来保护共享变量可能会导致额外的锁开销和上下文切换,从而影响性能。atomic 包的原子操作不需要使用锁,可以减少这些开销。
原子操作通常比互斥锁更高效,特别是在一些轻量级的操作中。在高并发的情况下,使用原子操作可以提高程序的性能。
适用场景
- 计数器和累加器: 当多个协程需要对一个共享的计数器或累加器进行增加、减少或重置操作时,使用 atomic包可以避免数据竞争,确保操作的原子性。
- 标志位和状态切换: 当多个协程需要读取和修改某个共享的标志位或状态值时,使用 atomic包可以确保状态的正确性,避免并发修改导致的问题。
- 缓存更新和缓存失效: 在缓存中存储的数据需要经常更新,且更新频率较高时,使用 atomic包可以保证更新操作的一致性,防止多个协程同时更新而导致的问题。
- 资源池管理: 当多个协程需要从资源池中获取或释放资源时,使用 atomic 包可以保证资源池的状态正确,避免资源泄漏和竞争条件。
- 引用计数: 在一些场景中,可能需要使用引用计数来管理共享资源的生命周期。使用 atomic 包可以确保引用计数的增加和减少操作是原子的。
atomic包中的函数
- atomic.AddInt32, atomic.AddInt64,atomic.AddUint32,atomic.AddUint64:原子地将指定的值加到一个整数变量上。
- atomic.LoadInt32,atomic.LoadInt64,atomic.LoadUint32,atomic.LoadUint64:原子地读取一个整数变量的值。
package main
import (
"fmt"
"sync"
"sync/atomic"
"time"
)
func main() {
var counter int64
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
for j := 0; j < 1000; j++ {
atomic.AddInt64(&counter, 1)
}
wg.Done()
}()
}
wg.Wait()
fmt.Println("Counter value:", atomic.LoadInt64(&counter))
}
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var value int64
var wg sync.WaitGroup
// 启动多个协程尝试存储值
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
// 原子地将值设置为协程的编号
atomic.StoreInt64(&value, int64(i))
fmt.Printf("Goroutine %d: Stored value %dn", i, i)
}(i)
}
wg.Wait()
fmt.Printf("Final value: %dn", value)
}
- atomic.CompareAndSwapInt32, atomic.CompareAndSwapInt64, atomic.CompareAndSwapUint32, atomic.CompareAndSwapUint64:比较并交换,比较当前addr地址里的值是不是old,如果不等于old,就返回false; 如果当前等于old,就把此地址的值替换成new值,返回true。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var value int64 = 0
var wg sync.WaitGroup
// 启动多个协程尝试修改值
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
// 尝试将值从旧值0修改为新值10
swapped := atomic.CompareAndSwapInt64(&value, 0, 10)
if swapped {
fmt.Printf("Goroutine %d: Value swapped successfullyn", i)
} else {
fmt.Printf("Goroutine %d: Value was not swappedn", i)
}
}(i)
}
wg.Wait()
fmt.Printf("Final value: %dn", value)
}
- atomic.SwapInt32, atomic.SwapInt64, atomic.SwapUint32, atomic.SwapUint64:原子地交换一个整数变量的值。如果不需要比较旧值,只是比较粗暴地替换的话,就可以使用Swap方法。
```go
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var value int64 = 5
var wg sync.WaitGroup
// 启动多个协程尝试交换值
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
// 原子地交换值为新值10,并获取旧值
oldValue := atomic.SwapInt64(&value, 10)
fmt.Printf("Goroutine %d: Swapped value from %d to 10n", i, oldValue)
}(i)
}
wg.Wait()
fmt.Printf("Final value: %dn", value)
}
原文地址:https://blog.csdn.net/ldxxxxll/article/details/134732420
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_29344.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。