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!