Go 葛朗:原子读是用来做什么的?

Go 葛朗:原子读是用来做什么的?,go,Go,这里我们有一个由go-by-Example提供的go案例来解释原子包 之后 opsFinal := ops fmt.Println("ops:", opsFinal) 问题3 我们是否担心这种情况 CPU从内存加载数据 CPU处理数据 将数据写回内存。虽然这一步很快,但仍然需要时间 当CPU执行步骤3时,另一个goroutine可能会从内存中读取不完整的脏数据。所以使用atomic.LoadUint64可以避免这种问题吗 参考文献 有必要使用原子.LoadUint64,因为不

这里我们有一个由
go-by-Example
提供的go案例来解释原子包

之后

    opsFinal := ops
    fmt.Println("ops:", opsFinal)
问题3 我们是否担心这种情况

  • CPU从内存加载数据
  • CPU处理数据
  • 将数据写回内存。虽然这一步很快,但仍然需要时间
  • 当CPU执行步骤3时,另一个goroutine可能会从内存中读取不完整的脏数据。所以使用
    atomic.LoadUint64
    可以避免这种问题吗

    参考文献
    有必要使用
    原子.LoadUint64
    ,因为不能保证
    :=
    操作符执行原子读取

    作为一个例子,考虑一个理论的例子:<代码>原子。AduTunt64 < /C> >实现如下:

  • 拿把锁
  • 读取较低的32位
  • 读取上面的32位
  • 将数字添加到较低的32位
  • 将第一个操作的进位添加到高32位
  • 写入较低的32位
  • 写入高32位
  • 松开锁
  • 如果不使用
    原子.LoadUint64
    ,则可能正在读取步骤6和步骤7之间的中间结果

    在某些平台上(例如,不支持64位整数操作的旧ARM处理器),它很可能以上述方式实现

    这同样适用于其他大小的整数/指针。确切的行为将取决于
    原子
    包的实现以及程序运行的CPU/内存体系结构

        opsFinal := atomic.LoadUint64(&ops) // Can I replace it?
        fmt.Println("ops:", opsFinal)
    
        opsFinal := ops
        fmt.Println("ops:", opsFinal)