我希望这两个goroutine永远阻止,原因如下,但事实并非如此。为什么呢?
频道没有缓冲区,等待receive()
接收。
send()
按住该锁定,num := <-s.ch
中的receive()
无法执行。
永远阻止
怎么了?
package main
import (
"sync"
"fmt"
)
type S struct {
mu sync.Mutex
ch chan int
wg sync.WaitGroup
}
func (s *S) send() {
s.mu.Lock()
s.ch <- 5
s.mu.Unlock()
s.wg.Done()
}
func (s *S) receive() {
num := <-s.ch
fmt.Printf("%d\n", num)
s.wg.Done()
}
func main() {
s := new(S)
s.ch = make(chan int)
s.wg.Add(2)
go s.send()
go s.receive()
s.wg.Wait()
}
答案 0 :(得分:2)
您的receive()
方法未使用锁定,因此持有锁定的send()
对receive()
无效。
由于send()
和receive()
都在他们自己的goroutine中运行,send()
会使其达到在频道上发送值5
的程度,因此receive()
中的接收可以继续进行,并且会在下一行打印出来。
另请注意,要使用来自多个goroutine的频道,您不需要&#34;外部&#34;同步。通道对于并发使用是安全的,数据竞争不能通过设计发生。有关详细信息,请参阅If I am using channels properly should I need to use mutexes?
如果receive()
方法也会使用这样的锁:
func (s *S) receive() {
s.mu.Lock()
num := <-s.ch
s.mu.Unlock()
fmt.Printf("%d\n", num)
}
然后是的,什么都不打印,因为在send()
释放锁定之前接收不会发生,但是直到有人从频道收到才会发生。
在这种情况下,程序将在1秒后终止而不打印任何内容,因为当睡眠结束时,主要的goroutine结束,整个应用程序也随之结束。它不会等待其他非主要的goroutine完成。有关详细信息,请参阅No output from goroutine in Go。
编辑:
是的,你误解了锁。锁定sync.Mutex
仅锁定互斥锁值本身,它不会锁定整个结构值(它不能锁定)。并且&#34;锁定价值本身&#34;表示如果另一个goroutine也调用其Mutex.Lock()
方法,该调用将阻塞,直到通过调用其Mutex.Unlock()
方法释放锁。解锁后,Mutex.Lock()
呼叫阻止的goroutine将继续锁定互斥锁并返回。