好的,Go"专家"。你会如何在惯用的Go中编写这段代码,又称没有next
中的互斥?
package main
import (
"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来处理状态,但我无法找到匹配输入/输出的方法。
答案 0 :(得分:3)
您将使用实际的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和channel来实现相同的效果
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)
答案 1 :(得分:1)
正如@favoretti所提到的,同步/原子是一种方法。
但是,你必须使用int32或int64而不是int(因为int在不同的平台上可以是不同的大小)。
以下是Playground
的示例(define (sort list length loop1 loop2 temp)
(cond ((>= loop1 length)
(list))
((< loop1 length)
(cond ((>= loop2 length)
(set! loop1 (+ loop1 1))
(set! loop2 (+ loop1 1)))
((< loop2 length)
(cond ((> (list-ref list loop1) (list-ref list loop2)))
(set-car! temp (list-ref list loop1))
(list-set! list loop1 (list-ref list loop2))
(list-set! list loop2 temp)
(set-car! temp '())
)
(set! loop2 (+ loop2 1))
)
)
(sort list length loop1 loop2 temp))
)