Go语言中什么操作叫做原子操作
Go语言中什么操作叫做原子操作
原子操作即是进行过程中不能被中断的操作,针对某个值的原子操作在被进行 的过程中,CPU 绝不会再去进行其他的针对该值的操作。为了实现这样的严谨性,原子操作仅会由一个独立的 CPU 指令代表和完成。原子操作是无锁的,常常直接通过 CPU 指令直接实现。 事实上,其它同步技术的实现常常依赖于原 子操作。
在Go语言中,原子操作指的是在执行过程中不会被线程(在Go中称为goroutine)调度机制打断的操作,这类操作在多线程环境中是安全的,无需使用互斥锁(mutexes)或其他同步机制即可保证数据的一致性和完整性。Go的sync/atomic
包提供了这类操作的实现。
原子操作通常用于对共享变量的简单操作,如自增、自减、加载(读取)、存储(写入)等,这些操作在执行时是原子的,即它们要么完全执行,要么完全不执行,不会出现只执行了一半的情况。
示例:使用sync/atomic
包进行原子操作
以下是一个使用sync/atomic
包中的AddInt32
函数对int32
类型变量进行原子自增操作的示例:
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var counter int32
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// 对counter进行原子自增操作
atomic.AddInt32(&counter, 1)
}()
}
wg.Wait() // 等待所有goroutine执行完毕
// 安全地读取counter的值
fmt.Println(counter) // 输出结果可能为10,但根据调度情况可能有所不同(理论上应该是10,因为每个goroutine都对其进行了+1操作)
}
注意:虽然上面的代码示例中每个goroutine都对counter
进行了+1操作,且使用了atomic.AddInt32
来确保操作的原子性,但由于fmt.Println(counter)
的调用不是原子的,且可能受到Go运行时调度的影响,所以在并发极高的情况下,最终打印的结果可能并不总是严格等于启动的goroutine数量(在这个例子中是10)。然而,atomic.AddInt32
的使用确保了每次+1操作的原子性,这是处理并发时保证数据一致性的关键。
在实际应用中,当你需要跨多个goroutine安全地更新或读取共享变量时,应该考虑使用sync/atomic
包提供的原子操作。