以下代码会产生奇怪现象。

https://github.com/golang/go/issues/28455


package main

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

// Node is a node in a linked list
type Node struct {
    Value int
    Next   *Node
}

// Cas swaps co.Next with a newly created Node that has a Value of i
func (co *Node) Cas(i int) int {
    cv := &Node{Value: i, Next: nil} //translated - make a new variable each time

    // swap co.Cur with the new variable
    ok := atomic.CompareAndSwapUintptr((*uintptr)(unsafe.Pointer(&co.Next)),
        uintptr(unsafe.Pointer(co.Next)),
        uintptr(unsafe.Pointer(cv)))

    // tells us that the swap happened successfully
    if !ok {
        fmt.Printf(" error ")
    } else {
        fmt.Printf(" ok ")
    }
    return co.Next.Value
}

// Prints out co.Cur.I
func (co *Node) NextValue() int {
    return co.Next.Value
}

func main() {
    fmt.Print("All numeric values on the same line should be equivalent\n\n")
    co := &Node{Next: &Node{}}
    for i := 1; i < 10; i++ {
        returned := co.Cas(i)
        fmt.Printf("i=%d, co.Cas(i)=%d, co.NextValue()=%d, co.Next.Value=%d\n", i, returned, co.NextValue(), co.Next.Value)
    }
}

=====输出结果为:

All numeric values on the same line should be equivalent

ok i=1, co.Cas(i)=1, co.NextValue()=1, co.Next.Value=4284456

ok i=2, co.Cas(i)=2, co.NextValue()=2, co.Next.Value=4284472

ok i=3, co.Cas(i)=3, co.NextValue()=3, co.Next.Value=4284488

ok i=4, co.Cas(i)=4, co.NextValue()=4, co.Next.Value=4284504

ok i=5, co.Cas(i)=5, co.NextValue()=5, co.Next.Value=4284520

ok i=6, co.Cas(i)=6, co.NextValue()=6, co.Next.Value=4284536

ok i=7, co.Cas(i)=7, co.NextValue()=7, co.Next.Value=4284552

ok i=8, co.Cas(i)=8, co.NextValue()=8, co.Next.Value=4284568

ok i=9, co.Cas(i)=9, co.NextValue()=9, co.Next.Value=4284584


注意其中的

co.Next.Value 与 co.NextValue() 的不同 , co.NextValue() 只是简单的返回了的co.Next.Value 值。 co.Next.Value 与 co.NextValue() 的不同 , co.NextValue() 只是简单的返回了的co.Next.Value 值。

已邀请:

axxapp - 攻城狮

赞同来自:

https://github.com/golang/go/issues/28455

atomic.CompareAndSwapUintptr 这个方法引用的对象会被GC回收,需要额外保持cv变量. Cas 方法被GC回收之后恰好被重复使用了

atomic.CompareAndSwapPointer 这个方法可以, 但我用go test 测试的时候,atomic.CompareAndSwapUintptr 性能好于 atomic.CompareAndSwapPointer

sheepbao - https://sheepbao.github.io 爱go,爱编程,领域网络开发,流媒体、分布式、网络加速

赞同来自:

二级指针操作链表,和我写过的文章其实是类似的 https://sheepbao.github.io/post/list_of_pointer_to_pointer/
但是也没明白为何你的操作会导致这样的结果,我看了Next的地址都是一样,应该不是GC的问题,你设置 GOGC=off 关闭gc试试。

要回复问题请先登录注册