英文:
Go atomic.AddFloat32()
问题
我需要一个在Go语言中原子地添加float32值的函数。根据我找到的一些C代码,这是我想出来的:
package atomic
import (
"sync/atomic"
"unsafe"
"math"
)
func AddFloat32(addr *float32, delta float32) (new float32) {
unsafeAddr := (*uint32)(unsafe.Pointer(addr))
for {
oldValue := math.Float32bits(*addr)
new = *addr + delta
newValue := math.Float32bits(new)
if atomic.CompareAndSwapUint32(unsafeAddr, oldValue, newValue) {
return
}
}
}
这个函数能正常工作吗(即真正地原子化)?在Go语言中有更好/更快的方法吗?
英文:
I need a function to atomically add float32 values in Go.
This is what came up with based on some C code I found:
package atomic
import (
"sync/atomic"
"unsafe"
"math"
)
func AddFloat32(addr *float32, delta float32) (new float32) {
unsafeAddr := (*uint32)(unsafe.Pointer(addr))
for {
oldValue := math.Float32bits(*addr)
new = *addr + delta
newValue := math.Float32bits(new)
if atomic.CompareAndSwapUint32(unsafeAddr, oldValue, newValue) {
return
}
}
}
Should it work (i.e really be atomic)? Is there a better/faster way to do it in Go?
答案1
得分: 9
从Go标准库中寻找一些代码进行适应。例如,从go/src/sync/atomic/64bit_arm.go
中:
func addUint64(val *uint64, delta uint64) (new uint64) {
for {
old := *val
new = old + delta
if CompareAndSwapUint64(val, old, new) {
break
}
}
return
}
对于float32
,可以这样修改:
package main
import (
"fmt"
"math"
"sync/atomic"
"unsafe"
)
func AddFloat32(val *float32, delta float32) (new float32) {
for {
old := *val
new = old + delta
if atomic.CompareAndSwapUint32(
(*uint32)(unsafe.Pointer(val)),
math.Float32bits(old),
math.Float32bits(new),
) {
break
}
}
return
}
func main() {
val, delta := float32(math.Pi), float32(math.E)
fmt.Println(val, delta, val+delta)
new := AddFloat32(&val, delta)
fmt.Println(val, new)
}
输出结果:
3.1415927 2.7182817 5.8598747
5.8598747 5.8598747
英文:
Look for some code from the Go standard library to adapt. For example, from go/src/sync/atomic/64bit_arm.go
,
func addUint64(val *uint64, delta uint64) (new uint64) {
for {
old := *val
new = old + delta
if CompareAndSwapUint64(val, old, new) {
break
}
}
return
}
For float32
that becomes,
package main
import (
"fmt"
"math"
"sync/atomic"
"unsafe"
)
func AddFloat32(val *float32, delta float32) (new float32) {
for {
old := *val
new = old + delta
if atomic.CompareAndSwapUint32(
(*uint32)(unsafe.Pointer(val)),
math.Float32bits(old),
math.Float32bits(new),
) {
break
}
}
return
}
func main() {
val, delta := float32(math.Pi), float32(math.E)
fmt.Println(val, delta, val+delta)
new := AddFloat32(&val, delta)
fmt.Println(val, new)
}
Output:
<pre>
3.1415927 2.7182817 5.8598747
5.8598747 5.8598747
</pre>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论