Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah `sync.Once` menggunakan `atomic.StoreUint32` dan bukannya tugasan biasa untuk bendera `done`?

Mengapakah `sync.Once` menggunakan `atomic.StoreUint32` dan bukannya tugasan biasa untuk bendera `done`?

Barbara Streisand
Barbara Streisandasal
2024-10-31 05:40:01679semak imbas

Why does `sync.Once` use `atomic.StoreUint32` instead of a regular assignment for the `done` flag?

AtomicStoreUint32 vs. Assignment in Sync.Once

Semasa menerokai kod sumber untuk penyegerakan Go.Setelah menaip, timbul persoalan mengenai penggunaan of atomic.StoreUint32 berbanding tugasan biasa untuk menetapkan bendera yang telah selesai.

Pelaksanaan Salah:

Kod sumber asal mengandungi pelaksanaan yang salah:

<code class="go">func (o *Once) Do(f func()) {
    if atomic.CompareAndSwapUint32(&o.done, 0, 1) {
        f()
    }
}</code>

Pelaksanaan ini gagal menjamin bahawa f selesai apabila fungsi kembali. Panggilan serentak boleh menyebabkan pemenang melaksanakan f manakala pemanggil kedua kembali serta-merta, dengan anggapan panggilan pertama selesai, yang mungkin tidak berlaku.

Pelaksanaan Betul:

Untuk membetulkan isu ini, pelaksanaan semasa menggunakan atomic.StoreUint32 bersama-sama dengan mutex:

<code class="go">func (o *Once) Do(f func()) {
    if atomic.LoadUint32(&o.done) == 0 {
        o.doSlow(f)
    }
}</code>
<code class="go">func (o *Once) doSlow(f func()) {
    o.m.Lock()
    defer o.m.Unlock()
    if o.done == 0 {
        defer atomic.StoreUint32(&o.done, 1)
        f()
    }
}</code>

Mengapa AtomicStoreUint32?

Penggunaan atomic .StoreUint32 adalah perlu untuk memastikan bahawa goroutine lain boleh melihat perubahan kepada o.dilakukan selepas f selesai. Walaupun penugasan primitif mungkin bersifat atom pada seni bina tertentu, model memori Go memerlukan penggunaan pakej atom untuk menjamin operasi atom merentas semua seni bina yang disokong.

Akses kepada Bendera Selesai:

Matlamatnya adalah untuk memastikan akses kepada bendera yang telah dibuat adalah selamat di luar mutex. Oleh itu, operasi atom digunakan dan bukannya mengunci dengan mutex. Pengoptimuman ini meningkatkan kecekapan laluan pantas, membolehkan penyegerakan. Sebaik sahaja digunakan dalam senario trafik tinggi.

Mutex untuk doSlow:

Mutex dalam doSlow memastikan bahawa hanya seorang pemanggil melaksanakan f sebelum o.done ditetapkan. atomic.StoreUint32 digunakan untuk menulis bendera kerana ia mungkin berlaku serentak dengan atomic.LoadUint32 di luar bahagian kritikal mutex.

Concurrent Writes vs. Reads:

Membaca terus o.dilakukan dalam doSlow adalah selamat kerana perlindungan mutex. Selain itu, membaca o.dilakukan serentak dengan atomic.LoadUint32 adalah selamat kerana kedua-dua operasi melibatkan pembacaan sahaja.

Atas ialah kandungan terperinci Mengapakah `sync.Once` menggunakan `atomic.StoreUint32` dan bukannya tugasan biasa untuk bendera `done`?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
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