Adakah Penulisan Serentak kepada `stdout` dalam Go Thread-Safe? Analisis Terperinci Kelakuan `fmt.Fprintf`.

DDD
Lepaskan: 2024-10-30 03:36:28
asal
334 orang telah melayarinya

Is Concurrent Writing to `stdout` in Go Thread-Safe? A Detailed Analysis of `fmt.Fprintf` Behaviour.

Concurrent Write on stdout: Thread Safety Analysis

Dalam perbincangan baru-baru ini, sekeping kod Go telah dibentangkan yang mencetuskan perdebatan tentang urutan keselamatan apabila menulis secara serentak kepada stdout. Kod yang dimaksudkan ialah:

<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>
Salin selepas log masuk

Pertimbangan Keselamatan Benang:

Persoalan timbul sama ada kod ini selamat untuk benang apabila berbilang goroutin menulis kepada stdout serentak. Pelbagai sumber dan pendapat mengenai perkara itu disebut tetapi jawapan yang pasti tidak ditemui. Mari kita mendalami topik ini dengan lebih lanjut.

Gelagat Pakej fmt:

Fungsi pakej fmt hanya mengambil implementasi io.Writer dan panggil Write() padanya. Fungsi itu sendiri adalah selamat untuk benang, bermakna berbilang panggilan serentak ke fungsi fmt.F* adalah selamat. Walau bagaimanapun, pelaksanaan penulisan serentak kepada stdout bergantung pada "penulis" khusus yang digunakan.

Pelaksanaan "Penulis":

Dua kategori utama "penulis" adalah berkaitan :

  • Pelaksanaan tersuai: Keselamatan benang ditentukan oleh pelaksanaan tersuai itu sendiri.
  • Pelaksanaan perpustakaan standard: Seperti *os. Pembungkus fail atau soket daripada pakej bersih. Pelaksanaan ini biasanya menyediakan pembalut "nipis" di sekeliling deskriptor atau soket fail asas.

Semantik POSIX:

Dalam kes deskriptor fail, POSIX memerlukan penulisan (2) panggilan menjadi atom apabila beroperasi pada fail biasa atau pautan simbolik. Ini bermakna dalam kes kami, di mana stdout diandaikan sebagai deskriptor fail, panggilan tulis hendaklah atom.

Perlaksanaan Perpustakaan Standard Go:

Pustaka standard Go pembalut di sekeliling deskriptor dan soket fail direka untuk memetakan operasi tulis 1-ke-1 kepada objek asas. Ini menghapuskan kemungkinan panggilan tulis dipecah atau dilekatkan bersama.

Kesimpulan:

Berdasarkan maklumat yang tersedia dan semantik asas panggilan tulis(2) POSIX , kod yang disediakan tidak tertakluk kepada perlumbaan data. Walau bagaimanapun, output yang ditulis kepada deskriptor fail asas mungkin dicampur dalam susunan yang tidak dapat diramalkan. Tingkah laku ini dipengaruhi oleh faktor seperti versi kernel OS, versi Go, perkakasan dan beban sistem.

Untuk memastikan bahawa output daripada setiap panggilan fmt.Fprint* tertentu muncul sebagai bahagian bersebelahan dalam output yang dihasilkan , adalah disyorkan untuk membuat siri panggilan menggunakan kunci atau menggunakan pakej log, yang menyediakan mekanisme pengunciannya sendiri.

Atas ialah kandungan terperinci Adakah Penulisan Serentak kepada `stdout` dalam Go Thread-Safe? Analisis Terperinci Kelakuan `fmt.Fprintf`.. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!