go学习笔记-sync/atomic
atomic包提供了底层的原子级内存操作,对于同步算法的实现很有用。
这些函数必须谨慎地保证正确使用。除了某些特殊的底层应用,使用通道或者sync包的函数/类型实现同步更好。
应通过通信来共享内存,而不通过共享内存实现通信。(官方原话:Share memory by communicating; don’t communicate by sharing memory. 这句话是go语言多线程编程的设计哲学!)
SwapT系列函数
被SwapT系列函数实现的交换操作,在原子性上等价于:
old = *addr
*addr = new
return old
例子:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var a int32 = 1
var b int32 = 2
c := atomic.SwapInt32(&a, b)
fmt.Println("a:", a)
fmt.Println("b:", b)
fmt.Println("c:", c)
}
结果:
a: 2
b: 2
c: 1
CompareAndSwapT系列函数(CAS算法)
CompareAndSwapT系列函数实现的比较-交换操作,在原子性上等价于:
if *addr == old {
*addr = new
return true
}
return false
例子1:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var a int32 = 1
var b int32 = 2
bool := atomic.CompareAndSwapInt32(&a, 1, b)
fmt.Println("a:", a)
fmt.Println("b:", b)
if bool {
fmt.Println("更新成功!")
} else {
fmt.Println("更新失败!")
}
}
结果:
a: 2
b: 2
更新成功!
例子2:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var a int32 = 1
var b int32 = 2
bool := atomic.CompareAndSwapInt32(&a, 3, b)
fmt.Println("a:", a)
fmt.Println("b:", b)
if bool {
fmt.Println("更新成功!")
} else {
fmt.Println("更新失败!")
}
}
结果:
a: 1
b: 2
更新失败!
AddT 系列函数
AddT 系列函数实现加法操作,在原子性上等价于:
*addr += delta
return *addr
LoadT和StoreT系列函数实现的加载和保持操作,在原子性上等价于:“return *addr"和”*addr = val"。
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var a int32 = 1
var b int32 = 2
c := atomic.AddInt32(&a, b)
fmt.Println("a:", a)
fmt.Println("b:", b)
fmt.Println("c:", c)
}
结果:
a: 3
b: 2
c: 3
LoadT和StoreT系列函数
LoadT和StoreT系列函数实现的加载和保持操作,在原子性上等价于:“return *addr"和”*addr = val"。
例子:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var a int32 = 1
b := atomic.LoadInt32(&a)
fmt.Println("a:", a)
fmt.Println("b:", b)
}
结果:
a: 1
b: 1
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var a int32 = 1
atomic.StoreInt32(&a, 2)
fmt.Println("a:", a)
}
结果:
a: 2
函数列表
函数名 | 说明 |
---|---|
func LoadInt32(addr *int32) (val int32) | LoadInt32原子性的获取*addr的值。 |
func LoadInt64(addr *int64) (val int64) | LoadInt64原子性的获取*addr的值。 |
func LoadUint32(addr *uint32) (val uint32) | LoadUint32原子性的获取*addr的值。 |
func LoadUint64(addr *uint64) (val uint64) | LoadUint64原子性的获取*addr的值。 |
func LoadUintptr(addr *uintptr) (val uintptr) | LoadPointer原子性的获取*addr的值。 |
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) | LoadPointer原子性的获取*addr的值。 |
func StoreInt32(addr *int32, val int32) | StoreUint32原子性的将val的值保存到*addr。 |
func StoreInt64(addr *int64, val int64) | StoreInt64原子性的将val的值保存到*addr。 |
func StoreUint32(addr *uint32, val uint32) | StoreUint32原子性的将val的值保存到*addr。 |
func StoreUint64(addr *uint64, val uint64) | StoreUint64原子性的将val的值保存到*addr。 |
func StoreUintptr(addr *uintptr, val uintptr) | StoreUintptr原子性的将val的值保存到*addr。 |
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) | StorePointer原子性的将val的值保存到*addr。 |
func AddInt32(addr *int32, delta int32) (new int32) | AddInt32原子性的将val的值添加到*addr并返回新值。 |
func AddInt64(addr *int64, delta int64) (new int64) | AddInt64原子性的将val的值添加到*addr并返回新值。 |
func AddUint32(addr *uint32, delta uint32) (new uint32) | AddUint32原子性的将val的值添加到*addr并返回新值。 如要减去一个值c,调用AddUint32(&x, ^uint32(c-1));特别的,让x减1,调用AddUint32(&x, ^uint32(0))。 |
func AddUint64(addr *uint64, delta uint64) (new uint64) | AddUint64原子性的将val的值添加到*addr并返回新值。 如要减去一个值c,调用AddUint64(&x, ^uint64(c-1));特别的,让x减1,调用AddUint64(&x, ^uint64(0))。 |
func AddUintptr(addr *uintptr, delta uintptr) (new uintptr) | AddUintptr原子性的将val的值添加到*addr并返回新值。 |
func SwapInt32(addr *int32, new int32) (old int32) | SwapInt32原子性的将新值保存到*addr并返回旧值。 |
func SwapInt64(addr *int64, new int64) (old int64) | SwapInt64原子性的将新值保存到*addr并返回旧值。 |
func SwapUint32(addr *uint32, new uint32) (old uint32) | SwapUint32原子性的将新值保存到*addr并返回旧值。 |
func SwapUint64(addr *uint64, new uint64) (old uint64) | SwapUint64原子性的将新值保存到*addr并返回旧值。 |
func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) | SwapUintptr原子性的将新值保存到*addr并返回旧值。 |
func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) | SwapPointer原子性的将新值保存到*addr并返回旧值。 |
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) | CompareAndSwapInt32原子性的比较addr和old,如果相同则将new赋值给addr并返回真。 |
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool) | CompareAndSwapInt64原子性的比较addr和old,如果相同则将new赋值给addr并返回真。 |
func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool) | CompareAndSwapUint32原子性的比较addr和old,如果相同则将new赋值给addr并返回真。 |
func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool) | CompareAndSwapUint64原子性的比较addr和old,如果相同则将new赋值给addr并返回真。 |
func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool) | CompareAndSwapUintptr原子性的比较addr和old,如果相同则将new赋值给addr并返回真。 |
func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) | CompareAndSwapPointer原子性的比较addr和old,如果相同则将new赋值给addr并返回真。 |