Golang中如何实现Stdout和Stderr的线程安全操作

Golang中如何实现Stdout和Stderr的线程安全操作 我在这里描述了这个问题:

github.com/golang/go

Thread-safe operation with Stdout and Stderr (exec. Cmd)

问题内容: 你使用的是哪个 Go 版本 (go version)? go version go1.16.4 windows/amd64 这个问题在最新版本中是否重现? 我不知道 什么…

请告诉我应该使用哪个线程安全的缓冲区?

3 回复

非常感谢

更多关于Golang中如何实现Stdout和Stderr的线程安全操作的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


type lockedReader struct {
    mu sync.Mutex
    r io.Reader
}

func (r *lockedReader) Read(b []byte) (n int, err error) {
    r.mu.Lock()
    defer r.mu.Unlock()
    return r.r.Read(b)
}

type lockedWriter struct {
    mu sync.Mutex
    w io.Writer
}

func (w *lockedWriter) Write(b []byte) (n int, err error) {
    w.mu.Lock()
    defer w.mu.Unlock()
    return w.w.Write(b)
}

func main() {
    stdout := &lockedWriter{w: os.Stdout}
    stdin := &lockedReader{r: os.Stdin}
    // 使用 stdout 和 stdin 替代 os.Stdout 和 os.Stdin。
}

在Go中实现os.Stdoutos.Stderr的线程安全操作,通常需要使用互斥锁(sync.Mutex)或原子操作来保护并发访问。由于标准输出和标准错误是共享资源,多个goroutine同时写入会导致输出混乱。

以下是一个示例,展示如何使用互斥锁来确保线程安全的写入操作:

package main

import (
    "fmt"
    "io"
    "os"
    "sync"
)

// 定义一个线程安全的writer结构
type safeWriter struct {
    mu sync.Mutex
    w  io.Writer
}

// 实现io.Writer接口的Write方法,使用互斥锁保护
func (sw *safeWriter) Write(p []byte) (n int, err error) {
    sw.mu.Lock()
    defer sw.mu.Unlock()
    return sw.w.Write(p)
}

func main() {
    // 创建线程安全的stdout和stderr writer
    safeStdout := &safeWriter{w: os.Stdout}
    safeStderr := &safeWriter{w: os.Stderr}

    // 启动多个goroutine同时写入
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            fmt.Fprintf(safeStdout, "Goroutine %d: stdout message\n", id)
            fmt.Fprintf(safeStderr, "Goroutine %d: stderr message\n", id)
        }(i)
    }
    wg.Wait()
}

如果你需要替换全局的os.Stdoutos.Stderr,可以使用os.Stdout = safeStdoutos.Stderr = safeStderr来重定向。但注意这会影响所有使用这些变量的代码。

对于exec.Cmd,你可以直接设置Cmd.StdoutCmd.Stderr为线程安全的writer:

cmd := exec.Command("some-command")
cmd.Stdout = safeStdout
cmd.Stderr = safeStderr
err := cmd.Run()

这样能确保命令输出的线程安全性。

回到顶部