io.Pipe Write()和Read()函数如何工作?

时间:2017-08-31 15:52:57

标签: go pipe

通过阅读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
}

1 个答案:

答案 0 :(得分:2)

互斥p.l用于读写sync.Cond条件,必要时会锁定和解锁它。

在条件上呼叫Wait会解锁其锁定,并等待相应的Signal呼叫。您可以看到管道使用p.wwaitp.rwait来协调ReadWrite方法中的读者和作者。