通过阅读golang src pipe.go来弄清楚管道是如何工作的,我遇到了这两个写()& read()函数。令我困惑的是,如果读者调用read()func并保持l.lock然后等待数据,那么writer如何调用write()func并获取l.lock来写入数据?
func (p *pipe) write(b []byte) (n int, err error) {
// pipe uses nil to mean not available
if b == nil {
b = zero[:]
}
// One writer at a time.
p.wl.Lock()
defer p.wl.Unlock()
p.l.Lock()
defer p.l.Unlock()
if p.werr != nil {
err = ErrClosedPipe
return
}
p.data = b
p.rwait.Signal()
for {
if p.data == nil {
break
}
if p.rerr != nil {
err = p.rerr
break
}
if p.werr != nil {
err = ErrClosedPipe
break
}
p.wwait.Wait()
}
n = len(b) - len(p.data)
p.data = nil // in case of rerr or werr
return
}
并阅读:
func (p *pipe) read(b []byte) (n int, err error) {
// One reader at a time.
p.rl.Lock()
defer p.rl.Unlock()
p.l.Lock()
defer p.l.Unlock()
for {
if p.rerr != nil {
return 0, ErrClosedPipe
}
if p.data != nil {
break
}
if p.werr != nil {
return 0, p.werr
}
p.rwait.Wait()
}
n = copy(b, p.data)
p.data = p.data[n:]
if len(p.data) == 0 {
p.data = nil
p.wwait.Signal()
}
return
}
答案 0 :(得分:2)
互斥p.l
用于读写sync.Cond
条件,必要时会锁定和解锁它。
在条件上呼叫Wait
会解锁其锁定,并等待相应的Signal
呼叫。您可以看到管道使用p.wwait
和p.rwait
来协调Read
和Write
方法中的读者和作者。