正常应该是恒定输出

test1 
test2 
........ 

但是只有test1输出,程序挂了,没有任何反应 指针的赋值是最基本的操作,这个应该是线程安全的,满足句号 但是这个测试没能

type Point struct { 
    X int 
    Y int 
} 
 
func main() { 
    var p *Point = nil 
    test := true 
    go func() { 
        for test { 
            if tmp := p; tmp == nil { 
                p = &Point{} 
            } 
        } 
    }() 
    go func() { 
        for test { 
            if tmp := p; tmp != nil { 
                p = nil 
            } 
        } 
    }() 
 
    n := 0 
    for test { 
        n++ 
        fmt.Printf("testing%v....\r\n",n) 
        time.Sleep(1000 * time.Millisecond) 
    } 
 
    fmt.Printf("test fail") 
} 

代码: https://play.golang.org/p/-NTq-2iyX5W

如果把指针改成int,这很好

func main() { 
    var p int = 0 
    test := true 
    go func() { 
        for test { 
            if tmp := p; tmp == 0 { 
                p = 1 
            } 
        } 
    }() 
    go func() { 
        for test { 
            if tmp := p; tmp != 0 { 
                p = 0 
            } 
        } 
    }() 
 
    n := 0 
    for test { 
        n++ 
        fmt.Printf("testing%v....\r\n",n) 
        time.Sleep(1000 * time.Millisecond) 
    } 
 
    fmt.Printf("test fail") 
} 

请您参考如下方法:

问题不仅在于有一场比赛,还在于有一场比赛时日程安排会出现问题。下面的代码有一些选项可以使这段代码产生所需的输出(它被注释掉了)。所以你要么:

  1. 添加一个锁来修复竞争条件[正确的方式]

  1. 为每个赛车程序添加一个小 sleep - 比赛继续存在

这段代码

package main 
 
import ( 
    "fmt" 
    "runtime" 
    "sync" 
    "time" 
) 
 
type Point struct { 
    X int 
    Y int 
} 
 
var lock sync.Mutex 
 
func main() { 
    // runtime.GOMAXPROCS(4) 
    fmt.Println("Max # of parallel processes = ", MaxParallelism()) 
 
    var p *Point = nil 
    test := true 
    go func() { 
        for test { 
            // lock.Lock() 
            if tmp := p; tmp == nil { 
                p = &Point{} 
            } 
            // lock.Unlock() 
            // time.Sleep(1 * time.Nanosecond) 
 
        } 
    }() 
    go func() { 
        for test { 
            // lock.Lock() 
            if tmp := p; tmp != nil { 
                p = nil 
            } 
            // lock.Unlock() 
            // time.Sleep(1 * time.Nanosecond) 
        } 
    }() 
 
    n := 0 
    for test { 
        n++ 
        fmt.Printf("testing%v....\r\n", n) 
        time.Sleep(1000 * time.Millisecond) 
    } 
 
    fmt.Printf("test fail") 
} 
 
func MaxParallelism() int { 
    maxProcs := runtime.GOMAXPROCS(0) 
    numCPU := runtime.NumCPU() 
    if maxProcs < numCPU { 
        return maxProcs 
    } 
    return numCPU 
} 

输出(在我的机器上。请注意,为了可能的并行计算,goroutines 的数量应该等于或小于虚拟处理器的数量):

go run main.go  
Max # of parallel processes =  4 
testing1.... 

尽管有 4 个虚拟处理器,但问题似乎是 main 在第一次 sleep 后永远不会被调度。显然,当存在竞争条件时,这会莫名其妙地(至少对我而言)养育它丑陋的头脑。另一个观察结果是,如果我们减少两个 goroutine 中的一个并继续修改 main 循环中的 p 变量,那么它就可以工作。所有这些似乎给人一种印象,即当存在竞争条件时,运行时处理的行为是不可预测的。


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!