如何实现指针值的原子操作

如何实现指针值的原子操作

1.CompareAndSwapPointer

在Go语言中,原子包提供lower-level原子内存,这对实现同步算法很有帮助。 Go语言中的CompareAndSwapPointer()函数用于对unsafe.Pointer值执行比较和交换操作。此函数在原子包下定义。在这里,您需要导入“sync/atomic”软件包才能使用这些函数。

用法:

func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
在这里,addr表示地址,old表示不安全。Pointer值是从SwapPointer操作返回的旧交换值,而new是unsafe.Pointer的新值,它将与旧交换值交换自身。

注意:(* unsafe.Pointer)是指向unsafe.Pointer值的指针。而且unsafe.Pointer类型有助于启用任意类型和内置uintptr类型之间的转换。此外,不安全是有助于Go程序的类型安全的软件包。

返回值:如果交换完成,则返回true,否则返回false。

2.SwapPointer

在Go语言中,原子包提供lower-level原子内存,这对实现同步算法很有帮助。 Go语言中的SwapPointer()函数用于将新值自动存储到* addr中,并返回先前的* addr值。此函数在原子包下定义。在这里,您需要导入“sync/atomic”软件包才能使用这些函数。

用法:

func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
在此,addr表示地址。而new是新的unsafe.Pointer值,而old是旧的unsafe.Pointer值。

注意:(* unsafe.Pointer)是指向unsafe.Pointer值的指针。而且unsafe.Pointer类型有助于启用任意类型和内置uintptr类型之间的转换。此外,不安全是有助于Go程序的类型安全的软件包。

返回值:它将新的unsafe.Pointer值存储到* addr中,并返回先前的* addr值。

3.StorePointer

在Go语言中,原子包提供lower-level原子内存,这对实现同步算法很有帮助。 Go语言中的StorePointer()函数用于将val原子存储到* addr中。此函数在原子包下定义。在这里,您需要导入“sync/atomic”包才能使用这些函数。

用法:

func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)
在此,addr表示地址。

注意: (* unsafe.Pointer)是指向unsafe.Pointer值的指针。而且unsafe.Pointer类型有助于启用任意类型和内置uintptr类型之间的转换。此外,不安全是有助于Go程序的类型安全的软件包。

返回值:它将val存储到* addr中,然后在需要时可以返回

4.LoadPointer

在Go语言中,原子包提供较低级别的原子内存,这对实现同步算法很有帮助。 Go语言中的LoadPointer()函数用于原子加载* addr。此函数在原子包下定义。在这里,您需要导入“sync/atomic”和“unsafe”软件包才能使用这些函数。

用法:

func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
在此,addr表示地址。

注意:(* unsafe.Pointer)是指向unsafe.Pointer值的指针。而且unsafe.Pointer类型有助于启用任意类型和内置uintptr类型之间的转换。此外,不安全是有助于Go程序的类型安全的软件包。

返回值:它会自动加载* addr并返回unsafe.Pointer。

综合案例:
package main

import (
	"log"
	"sync/atomic"
	"unsafe"
)

func init() {
	log.SetFlags(log.LstdFlags)
}

type User struct {
	Name string
	Age  int
}

func main() {
	var ptr unsafe.Pointer
	//存储一个指针
	user1 := &User{Name: "test1", Age: 30}
	log.Printf("user1.prr:%p; ptr.ptr:%v", user1, ptr)
	atomic.StorePointer(&ptr, unsafe.Pointer(user1))

	//ptr本身的就是指针,不需要使用%p进行格式化输出
	log.Printf("user1.ptr:%p; ptr.ptr:%v", user1, ptr)
	//ptr本身的就是指针,不需要使用%p进行格式化输出
	user2 := (*User)(atomic.LoadPointer(&ptr))
	log.Printf("%+v", *user2)

	log.Printf("user2.ptr:%p;ptr.ptr:%v", user2, ptr)

	//交换指针
	user3 := &User{Name: "test2", Age: 25}
	oldValue := atomic.SwapPointer(&ptr, unsafe.Pointer(&user3))
	log.Println("oldValue:", (*User)(oldValue), "newValue:", (*User)(atomic.LoadPointer(&ptr)))
	//ptr的地址发生了改,指向了user3
	log.Printf("user3.ptr:%p; ptr.ptr:%v", user3, ptr)

	//比较交换指针
	swapped := atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(user2), unsafe.Pointer(user1))
	log.Println(swapped)
	user4 := &User{Name: "test2", Age: 25}
	log.Printf("user3.ptr:%p ; user4.ptr:%p", user3, user4)
	swapped = atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(user3), unsafe.Pointer(user1))
	log.Println(swapped)

	//将ptr的地址指向了user1
	log.Printf("user1.ptr:%p;ptr.ptr:%v", user1, ptr)
	log.Printf("user1:%+v;user3:%+v", user1, user3)
	// 加载交换后的指针并转换为对应类型
	user5 := (*User)(atomic.LoadPointer(&ptr))
	log.Println(user5)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值