为了账号安全,请及时绑定邮箱和手机立即绑定

无互斥量。

无互斥量。

Go
扬帆大鱼 2021-11-08 18:48:27
好吧,去“专家”。你会如何用惯用的 Go 编写这段代码,也就是没有互斥锁next?package mainimport (    "fmt")func main() {    done := make(chan int)    x := 0    for i := 0; i < 10; i++ {        go func() {            y := next(&x)            fmt.Println(y)            done <- 0        }()    }    for i := 0; i < 10; i++ {        <-done    }    fmt.Println(x)}var mutex = make(chan int, 1)func next(p *int) int {    mutex <- 0    // critical section BEGIN    x := *p    *p++    // critical section END    <-mutex    return x}假设你不能同时在临界区有两个 goroutine,否则会发生不好的事情。我的第一个猜测是有一个单独的 goroutine 来处理状态,但我想不出匹配输入/输出的方法。
查看完整描述

2 回答

?
墨色风雨

TA贡献1853条经验 获得超6个赞

您将使用实际的 sync.Mutex:


var mutex sync.Mutex


func next(p *int) int {

    mutex.Lock()

    defer mutex.Unlock()

    x := *p

    *p++

    return x

}

尽管您可能还会将next功能、状态和 sync.Mutex 组合到一个结构中。


虽然在这种情况下没有理由这样做,因为 Mutex 更适合围绕单个资源进行互斥,您可以使用 goroutines 和通道来实现相同的效果


http://play.golang.org/p/RR4TQXf2ct


x := 0


var wg sync.WaitGroup

send := make(chan *int)

recv := make(chan int)


go func() {

    for i := range send {

        x := *i

        *i++

        recv <- x

    }

}()


for i := 0; i < 10; i++ {

    wg.Add(1)

    go func() {

        defer wg.Done()

        send <- &x

        fmt.Println(<-recv)

    }()

}

wg.Wait()

fmt.Println(x)


查看完整回答
反对 回复 2021-11-08
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

正如@favoretti 提到的,同步/原子是一种方法。


但是,您必须使用 int32 或 int64 而不是 int (因为 int 在不同平台上的大小可能不同)。


这是Playground上的一个例子


package main


import (

    "fmt"

    "sync/atomic"

)


func main() {

    done := make(chan int)

    x := int64(0)

    for i := 0; i < 10; i++ {

        go func() {

            y := next(&x)

            fmt.Println(y)

            done <- 0

        }()

    }

    for i := 0; i < 10; i++ {

        <-done

    }

    fmt.Println(x)


}


func next(p *int64) int64 {

    return atomic.AddInt64(p, 1) - 1

}


查看完整回答
反对 回复 2021-11-08
  • 2 回答
  • 0 关注
  • 183 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信