Go-Atomic应用
atomic 操作的对象是一个地址,你需要把可寻址的变量的地址作为参数传递给方法,而不是把变量的值传递给方法。
提供的方法有:
Add
func AddInt32(addr *int32, delta int32) (new int32)
给一个地址上的内容加上值,返回新的值
CAS
func CompareAndSwapInt32(addr *int32, old, new int32)(swapped bool)
比较并替换某个地址上的值,返回成功或失败。
因此代码里常用循环,失败后再次操作
Swap
func SwapInt32(add *int32, new int32) (old int32)
不比较旧值,直接替换,返回替换的值,因此并发时每个返回的替换值是不同的。
Load
func LoadInt32(add *int32) (val int32)
取出addr地址中的值,即使在多处理器、多核、有 CPU cache 的情况下,这个操作也能保证 Load 是一个原子操作。
Store
func StoreInt32(add *int32, val int32)
把一个值存到指定的addr地址中,即使在多处理器、多核、有 CPU cache 的情况下,这个操作也能保证 Store 是一个原子操作。别的 goroutine 通过 Load 读取出来,不会看到存取了一半的值。它支持的数据类型和方法如图所示。
和Swap相比,没有返回值。
以上这些原子操作,可操作的类型包括int32 int64 uint32 uint64 unsafe.Pointer uintptr
atomic提供一种特殊的类型:Value,可以原子的存去对象类型,不能CAS和Swap,常常用在配置变更等场景中。
func(v *Value) Load(x interface{})
func(v *value) Store(x interface{})
实现一个无锁队列
package lockfree
import (
"sync/atomic"
"unsafe"
)
type LKQueue struct {
head unsafe.Pointer
tail unsafe.Pointer
}
type node struct {
value interface{}
next unsafe.Pointer
}
func NewLKQueue() *LKQueue {
n := unsafe.Pointer(&node{})
return &LKQueue{head: n, tail: n}
}
func (q *LKQueue) Enqueue(v interface{}){
n := &node{value: v}
for{
tail := load(&q.tail) // node类型
next := load(&tail.next) // 这里可能也被赋值了
// 尾节点未变化
if tail == load(&q.tail) {
if next == nil {
if cas(&tail.next, next, n) {
cas(&q.tail, tail, n)
return
}
} else {
cas(&q.tail, tail, next) // 这里需要做吗?
}
}
//tail.next = n;
//n.next = nil
}
}
func (q *LKQueue) Dequeue() interface{} {
for{
head := load(&q.head)
tail := load(&q.tail)
next := load(&head.next)
if head == load(&q.head) { //head没变
if head == tail {
if next == nil {
return nil
}
cas(&q.tail, tail, next)
} else {
v := next.value
if cas(&q.head, head, next) {
return v
}
}
}
}
}
func load(p *unsafe.Pointer) (n *node){
return (*node)(atomic.LoadPointer(p))
}
func cas(p *unsafe.Pointer, old, new *node) (ok bool) {
return atomic.CompareAndSwapPointer(p, unsafe.Pointer(old), unsafe.Pointer(new))
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术