ホームページ  >  記事  >  バックエンド開発  >  Go での「stdout」への書き込みは本当にスレッドセーフですか?

Go での「stdout」への書き込みは本当にスレッドセーフですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-27 07:10:02412ブラウズ

 Is Writing to `stdout` in Go Truly Thread-Safe?

標準出力への同時書き込みはスレッドセーフですか?

この質問は、標準出力 (stdout) ストリームへの同時書き込みのスレッド セーフに関するものです。行く。具体的には、次のコードを考えてみましょう。

<code class="go">package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    x := strings.Repeat(" ", 1024)
    go func() {
        for {
            fmt.Fprintf(os.Stdout, x+"aa\n")
        }
    }()

    go func() {
        for {
            fmt.Fprintf(os.Stdout, x+"bb\n")
        }
    }()

    go func() {
        for {
            fmt.Fprintf(os.Stdout, x+"cc\n")
        }
    }()

    go func() {
        for {
            fmt.Fprintf(os.Stdout, x+"dd\n")
        }
    }()

    <-make(chan bool)
}</code>

明らかなデータ競合がないにもかかわらず、このコードのスレッド セーフについては議論があります。この問題を明確にするために、stdout への書き込みの仕組みを詳しく調べ、推奨事項とリファレンスを調べてみましょう。

FMT パッケージと IO.Writer

fmt パッケージの機能fmt.Fprintf など、io.Writer インターフェイスを実装する引数を受け入れます。これらは、このインターフェイスの Write メソッドを内部で呼び出します。

OS と stdout への同時アクセス

os.Stdout は、出力を次の宛先に送信する io.Writer インターフェイスの実装です。システムの標準出力。複数のゴルーチンが同時に os.Stdout に書き込む場合、この操作の実際のセマンティクスは基礎となるオペレーティング システムに委任されます。

POSIX システムの場合は、write(2) システム コールが使用されます。 POSIX では、通常のファイルとシンボリック リンクに対して、同時 write(2) 呼び出しがアトミックであると指定されています。ただし、この保証は他のファイル タイプや非 POSIX システムには適用されません。

Go 標準ライブラリとラッパー

Go 標準ライブラリは、書き込み用のラッパーを提供します。ファイル記述子とソケット。これらのラッパーは io.Writer インターフェイスを実装し、os.Stdout の場合、操作を関連するシステム コールにリダイレクトします。

Go ランタイムは、これらのラッパーが同時アクセスに対して内部的に安全であることを保証します。ただし、基礎となるオペレーティング システムに書き込みを中継するだけなので、同時実行のセマンティクスは最終的に OS によって決定されます。

標準出力同時書き込みの影響

  • fmt.Fprintf への同時呼び出しと os.Stdout への書き込みは、Go ランタイム内で同時に使用しても安全です。
  • 出力の実際の順序は決定的ではなく、OS、Go ランタイム、

推奨事項

  • 標準出力への同時書き込みからの出力順序が重要な場合は、同期メカニズムを使用して特定の負荷を強制することを検討してください。
  • ログ パッケージは、制御可能なタイムスタンプとログ ヘッダーを備えた stdout (または他の宛先) へのスレッドセーフなログ記録を含むログ フレームワークを提供します。

参照

  • POSIX write(2) システムコール: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
  • Go の io.Writer インターフェイス: https://pkg.go.dev/io#Writer
  • Go の Fmt パッケージ: https://pkg.go.dev/fmt
  • Go のログ パッケージ: https:// pkg.go.dev/log

以上がGo での「stdout」への書き込みは本当にスレッドセーフですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。