Rumah > Artikel > pembangunan bahagian belakang > Bagaimana untuk menggunakan kunci dalam Go?
Dalam pengaturcaraan serentak, kunci ialah mekanisme yang digunakan untuk melindungi sumber yang dikongsi. Dalam bahasa Go, kunci adalah salah satu alat penting untuk mencapai keselarasan. Ia memastikan bahawa apabila sumber dikongsi diakses secara serentak oleh berbilang coroutine, hanya satu coroutine boleh membaca atau mengubah suai sumber ini. Artikel ini akan memperkenalkan penggunaan kunci dalam bahasa Go untuk membantu pembaca lebih memahami pengaturcaraan serentak.
Kunci Pengecualian Bersama ialah mekanisme penguncian yang paling biasa digunakan dalam bahasa Go. Ia memastikan bahawa hanya satu coroutine boleh mengakses bahagian kritikal pada masa yang sama. Dalam istilah orang awam, kunci mutex memastikan bahawa hanya satu coroutine boleh mengaksesnya pada masa yang sama dengan membungkus sumber yang dikongsi dalam bahagian kritikal kunci.
Menggunakan kunci mutex dalam bahasa Go adalah sangat mudah. Kita boleh menggunakan jenis Mutex dalam pakej penyegerakan untuk mencipta kunci mutex:
import "sync" var mutex = &sync.Mutex{}
Selepas itu, di lokasi sumber yang dikongsi perlu dilindungi, kita boleh menggunakan kod berikut untuk memperoleh kunci:
mutex.Lock() defer mutex.Unlock()
berbaloi Ambil perhatian bahawa kunci mutex tidak menyokong kemasukan semula. Jika coroutine telah memperoleh kunci, cuba mendapatkan kunci itu semula akan mengakibatkan kebuntuan. Oleh itu, kami biasanya menggunakan pernyataan penangguhan untuk melepaskan kunci secara automatik apabila coroutine tamat.
Berikut ialah contoh penggunaan mutex:
import ( "fmt" "sync" ) var count = 0 var mutex = &sync.Mutex{} func increment(wg *sync.WaitGroup) { mutex.Lock() defer mutex.Unlock() count++ wg.Done() } func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go increment(&wg) } wg.Wait() fmt.Println("Count:", count) }
Dalam contoh ini, kami menggunakan mutex untuk melindungi kaunter. 1000 coroutine melaksanakan fungsi kenaikan pada masa yang sama, menambah 1 pada kaunter setiap kali. Disebabkan oleh penggunaan kunci mutex, program boleh mengeluarkan nilai pembilang akhir dengan betul.
Dalam persekitaran berbilang coroutine, Kunci Baca-Tulis mungkin lebih baik daripada kunci mutex. Sebaliknya, ia boleh kekal cekap apabila berbilang coroutine membaca daripada sumber yang dikongsi secara serentak, tetapi masih memerlukan akses yang saling eksklusif apabila terdapat operasi tulis.
Kunci baca-tulis terdiri daripada dua jenis kunci: kunci baca dan kunci tulis. Kunci baca membenarkan berbilang coroutine mengakses sumber yang dikongsi pada masa yang sama, tetapi kunci tulis memastikan bahawa hanya satu coroutine boleh mengaksesnya pada masa yang sama.
Dalam bahasa Go, anda boleh menggunakan jenis RWMutex dalam pakej penyegerakan untuk mencipta kunci baca-tulis.
import "sync" var rwlock = &sync.RWMutex{}
Kaedah pemerolehan kunci baca dan kunci tulis adalah berbeza. Berikut ialah beberapa penggunaan biasa:
Berikut ialah contoh penggunaan kunci baca-tulis:
import ( "fmt" "sync" ) var count = 0 var rwlock = &sync.RWMutex{} func increment(wg *sync.WaitGroup) { rwlock.Lock() defer rwlock.Unlock() count++ wg.Done() } func read(wg *sync.WaitGroup) { rwlock.RLock() defer rwlock.RUnlock() fmt.Println("Count:", count) wg.Done() } func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go increment(&wg) } wg.Wait() for i := 0; i < 5; i++ { wg.Add(1) go read(&wg) } wg.Wait() }
Dalam ini contoh , kami membuka 10 coroutine secara serentak untuk menulis data ke kaunter dan 5 coroutine untuk membaca data kaunter. Dengan menggunakan kunci baca-tulis, atur cara boleh membaca daripada sumber yang dikongsi dengan cara yang cekap sambil memastikan keatoman operasi tulis.
Dalam bahasa Go, anda juga boleh menggunakan operasi atom untuk memastikan bahawa operasi primitif penyegerakan adalah atom. Operasi atom tidak memerlukan penguncian dan oleh itu lebih cekap daripada kunci dalam beberapa situasi.
Bahasa Go mempunyai berbilang fungsi operasi atom terbina dalam, anda boleh merujuk kepada dokumentasi rasmi. Berikut ialah dua fungsi operasi atom yang biasa digunakan: atomic.Add dan atomic.Load.
Berikut ialah contoh:
import ( "fmt" "sync/atomic" "time" ) var count int32 = 0 func increment(wg *sync.WaitGroup) { defer wg.Done() atomic.AddInt32(&count, 1) } func printCount() { fmt.Println("Count: ", atomic.LoadInt32(&count)) } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go increment(&wg) } wg.Wait() printCount() time.Sleep(time.Second) for i := 0; i < 3; i++ { wg.Add(1) go increment(&wg) } wg.Wait() printCount() }
Dalam contoh ini, kami menggunakan fungsi atom.Tambah untuk melaksanakan operasi penambahan atom pada pembilang, dan fungsi atom.Muatkan ke membaca nilai pembilang secara atom. Dengan menggunakan operasi atom, kita boleh mengelakkan overhed kunci dan mencapai pengaturcaraan serentak yang lebih cekap.
Bahasa Go menyediakan pelbagai mekanisme penyegerakan, termasuk kunci mutex, kunci baca-tulis dan operasi atom. Menggunakan mekanisme penyegerakan yang sesuai dalam pengaturcaraan serentak adalah kunci untuk memastikan program berjalan dengan betul dan cekap. Untuk mengelakkan kebuntuan, kita perlu memikirkan dengan teliti tentang mekanisme kunci mana yang paling sesuai untuk sumber yang dikongsi semasa. Dalam bahasa Go, cara menggunakan kunci adalah sangat mudah. Perlu diingatkan bahawa masa memegang kunci harus dikurangkan sebanyak mungkin untuk mengelakkan pengurangan prestasi program.
Atas ialah kandungan terperinci Bagaimana untuk menggunakan kunci dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!