go - 在一个变量中存储 2 个值

标签 go binary bit-shift bit

这段 Go 代码是否正确且可移植,我需要在一个变量中存储 2 个计数器(每次调用只会更新一个计数器)以避免在我将使用单个 atomic.AddUint64() 而不是实际代码中锁定锁定整个结构。

package main

import "fmt"

var long uint64 // Actual counters storage

func main() {
    left := uint32(100) // First counter
    right := uint32(200) // Second counter
    long = uint64(left)
    long = long << 32 | uint64(right)
    fmt.Println(left, right)

    long += uint64(1 << 32) // Increment left
    long += 1 // Increment right

    xLeft := uint32(long >> 32) // Get left
    xRight := uint32(long) // Get right
    fmt.Println(xLeft, xRight)
}

http://play.golang.org/p/aBlp-Zatgn

最佳答案

Is this Go code correct and portable

这是正确的,只要您使用 64 位宽度的无符号整数。

在这种情况下,sync/atomic 包为 Go 编译器支持的架构提供了可移植性。但是请注意,并非所有体系结构都支持对 64 位宽数据进行“真正的”原子操作。例如,the i386 implementation使用 CAS 循环:

TEXT ·AddUint64(SB),NOSPLIT,$0-20
    // no XADDQ so use CMPXCHG8B loop
    MOVL    addr+0(FP), BP
    TESTL   $7, BP
    JZ  2(PC)
    MOVL    0, AX // crash with nil ptr deref
    // DI:SI = delta
    MOVL    delta_lo+4(FP), SI
    MOVL    delta_hi+8(FP), DI
    // DX:AX = *addr
    MOVL    0(BP), AX
    MOVL    4(BP), DX
addloop:
    // CX:BX = DX:AX (*addr) + DI:SI (delta)
    MOVL    AX, BX
    MOVL    DX, CX
    ADDL    SI, BX
    ADCL    DI, CX

    // if *addr == DX:AX {
    //  *addr = CX:BX
    // } else {
    //  DX:AX = *addr
    // }
    // all in one instruction
    LOCK
    CMPXCHG8B   0(BP)

    JNZ addloop

    // success
    // return CX:BX
    MOVL    BX, new_lo+12(FP)
    MOVL    CX, new_hi+16(FP)
    RET

这可能会引发一个问题:为什么不使用带锁的结构?


编辑以回答评论中的问题:是的,使用 32 位整数将导致在所有 Go 支持的架构上进行实际的原子操作,因为它们都支持 XADDL(或模拟)到最好的我的知识。

关于go - 在一个变量中存储 2 个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30391141/

相关文章:

go - 在 golang 中使用 gmail API 发送带附件的电子邮件

mysql - Golang db.Query with sql join

python - 构建 bsdiff 模块失败

c++ - unsigned int 的位移,为什么是负数?

unit-testing - 是否可以将 golang 单元测试结果打印到文件中?

Go:类型切换断言中的这种多案例条件有什么问题?

java - 如何在 BDD 中编码整数

java - 如何使用java读取给定的二进制结构?

c++ - 零位移位会正常工作吗?

c - C 中位级别的显式类型转换