douhuan1901 2015-05-22 07:48
浏览 24
已采纳

将2个值存储在一个变量中

Is this Go code correct and portable, I need to store 2 counters (each call only one counter will be updated) in one variable to avoid locks in actual code where I am going to use single atomic.AddUint64() instead of locking whole struct.

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

  • 写回答

1条回答 默认 最新

  • dqeq885710 2015-05-22 08:40
    关注

    Is this Go code correct and portable

    It is correct, as long as you work with unsigned integers of 64-bit width.

    Portability in this case is provided by the sync/atomic packages to the architectures supported by the Go compiler. Note, however, that not all architectures support "true" atomic operations on 64-bit wide data. For example, the i386 implementation uses a CAS-loop:

    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
    

    That may open the question: why not use a struct with a lock?


    Edit to answer question in comments: Yes, using a 32-bit integer would result in actual atomic operations on all Go-supported architectures because they all support XADDL (or analog) to the best of my knowledge.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 pb数据库修改或者求完整pb库存系统,需为pb自带数据库
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路