簡體   English   中英

Go bytes.Buffer 是線程安全的嗎?

[英]Is the Go bytes.Buffer thread-safe?

Go編程語言中, bytes.Buffer是線程安全的嗎? AFAIK,它的文檔沒有提到線程安全。

不。

Go 文檔遵循一個簡單的規則:如果沒有明確聲明並發訪問某物是安全的,那么它就不是。

不 - 但您可以輕松地將它包裝在一個線程安全的結構中!

對於簡單的事情:

type Buffer struct {
    b bytes.Buffer
    m sync.Mutex
}
func (b *Buffer) Read(p []byte) (n int, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.Read(p)
}
func (b *Buffer) Write(p []byte) (n int, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.Write(p)
}
func (b *Buffer) String() string {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.String()
}

..並像往常一樣使用它var buf Buffer等。

想要更多 bytes.Buffer 嗎? 隨意挑選:

func (b *Buffer) Bytes() []byte {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.Bytes()
}
func (b *Buffer) Cap() int {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.Cap()
}
func (b *Buffer) Grow(n int) {
    b.m.Lock()
    defer b.m.Unlock()
    b.b.Grow(n)
}
func (b *Buffer) Len() int {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.Len()
}
func (b *Buffer) Next(n int) []byte {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.Next(n)
}
func (b *Buffer) ReadByte() (c byte, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.ReadByte()
}
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.ReadBytes(delim)
}
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.ReadFrom(r)
}
func (b *Buffer) ReadRune() (r rune, size int, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.ReadRune()
}
func (b *Buffer) ReadString(delim byte) (line string, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.ReadString(delim)
}
func (b *Buffer) Reset() {
    b.m.Lock()
    defer b.m.Unlock()
    b.b.Reset()
}
func (b *Buffer) Truncate(n int) {
    b.m.Lock()
    defer b.m.Unlock()
    b.b.Truncate(n)
}
func (b *Buffer) UnreadByte() error {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.UnreadByte()
}
func (b *Buffer) UnreadRune() error {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.UnreadRune()
}
func (b *Buffer) WriteByte(c byte) error {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.WriteByte(c)
}
func (b *Buffer) WriteRune(r rune) (n int, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.WriteRune(r)
}
func (b *Buffer) WriteString(s string) (n int, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.WriteString(s)
}
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
    b.m.Lock()
    defer b.m.Unlock()
    return b.b.WriteTo(w)
}

使用io.Pipe()函數調用,它提供一對連接對象( *PipeReader*PipeWriter )用於同步讀/寫。 這可以並行完成,並且它是線程安全的。

在Go編程語言中, bytes.Buffer是線程安全的嗎? AFAIK,其文檔中沒有提及線程安全性。

bytes.Buffer 不是線程安全的,但這里有一個使用“通道和通信”安全地寫入 Buffer(或任何 io.StringWriter)的示例。

type SyncWriter struct {
    w      io.StringWriter
    finish sync.WaitGroup
    queue  chan string
    err    error
}

func NewSyncWriter(w io.StringWriter) *SyncWriter {
    var t SyncWriter
    t.w = w
    t.queue = make(chan string, 5)
    t.finish.Add(1)
    go t.writer()
    return &t
}

func (t *SyncWriter) Close() error {
    close(t.queue)
    t.finish.Wait()
    return t.err
}

func (t *SyncWriter) WriteString(s string) (int, error) {
    t.queue <- s
    return len(s), nil
}

func (t *SyncWriter) Write(p []byte) (int, error) {
    return t.WriteString(string(p))
}

func (t *SyncWriter) writer() {
    defer t.finish.Done()
    for s := range t.queue {
        _, err := t.w.WriteString(s)
        if err != nil && t.err == nil {
            t.err = err
        }
    }
}

下面是如何使用它:

func write(wg *sync.WaitGroup, w io.Writer, d int) {
    fmt.Fprintf(w, "%d", d)
    wg.Done()
}

func main() {
    var buf bytes.Buffer
    w := NewSyncWriter(&buf)
    w.WriteString("hello ")
    var wg sync.WaitGroup
    wg.Add(10)
    for i := 0; i < 10; i++ {
        go write(&wg, w, i)
    }
    wg.Wait()
    w.Close()
    fmt.Printf("%s\n", buf.String())
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM