Golang ialah bahasa pengaturcaraan yang cekap dan ringkas, dan prestasi baik serta kemudahan penggunaannya ditunjukkan dalam aplikasi pengaturcaraan serentak. Dalam pengaturcaraan serentak, Mutex ialah mekanisme penyegerakan yang sangat biasa. Ia boleh memastikan akses yang saling eksklusif kepada sumber yang dikongsi dalam persekitaran berbilang benang sambil mengelakkan keadaan perlumbaan (iaitu, hasil yang tidak dapat diramalkan apabila berbilang rangkaian mengakses sumber dikongsi pada masa yang sama). Artikel ini akan memperkenalkan prinsip pelaksanaan asas Mutex.
1. Definisi Mutex
Di Golang, Mutex ialah mekanisme penyegerakan yang digunakan untuk melindungi akses yang saling eksklusif kepada sumber yang dikongsi. Ia mengandungi dua kaedah: Lock() dan Unlock(), yang digunakan untuk mengunci dan membuka kunci Mutex masing-masing. Apabila benang memperoleh kunci Mutex, benang lain akan disekat sehingga kunci dilepaskan.
2. Pelaksanaan asas Mutex
Di Golang, pelaksanaan asas Mutex bergantung terutamanya pada struktur yang dipanggil penyegerakan.Mutex. Pelaksanaan Mutex dilaksanakan melalui operasi CAS (Compare-And-Swap), yang bergantung pada operasi atom perkakasan asas.
Struktur Mutex ditakrifkan seperti berikut:
type Mutex struct { state int32 sema *uint32 // 信号量 } const ( mutexLocked = 1 << iota // mutex is locked ) func (m *Mutex) Lock() { // Fast path: 这里如果加锁成功,就直接返回 if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) { return } // Slow path : 防止出现busy spinning,将当前协程加入等待队列,然后调用runtime.semacquire继续sleep。 sema := m.sema if sema == nil { sema = new(uint32) m.sema = sema } runtime_Semacquire(sema) } func (m *Mutex) Unlock() { // Fast path: 这里如果释放锁成功,就直接返回 if atomic.CompareAndSwapInt32(&m.state, mutexLocked, 0) { return } // Slow path: 如果锁还被持有,则调用sync.runtime_Semrelease继续唤醒协程。 sema := m.sema if sema == nil { panic("sync: unlock of unlocked mutex") } runtime_Semrelease(sema, false, 1) }
Struktur Mutex mengandungi dua medan, keadaan dan semafora. Antaranya, keadaan menunjukkan status kunci, mutexLocked menunjukkan bahawa ia dikunci, dan nilai lain menunjukkan bahawa ia tidak dikunci. sema digunakan untuk menyelaraskan goroutine menunggu kunci.
Dalam kaedah Mutex.Lock(), jika Mutex semasa tidak dikunci, gunakan operasi atom CompareAndSwapInt32 untuk menukar keadaan daripada 0 kepada mutexLocked, dan kembali terus selepas berjaya, jika tidak, biarkan goroutine semasa bergabung baris gilir menunggu, Dan panggil kaedah runtime.semacquire() untuk membangunkannya. Dalam kaedah Mutex.Unlock(), jika Mutex semasa dikunci, gunakan operasi atom CompareAndSwapInt32 untuk menukar keadaan daripada mutexLocked kepada 0, dan kembali terus selepas kejayaan jika tidak, pengecualian dilemparkan, menunjukkan bahawa Mutex semasa tidak terkunci.
Terdapat laluan pantas dan laluan perlahan dalam kedua-dua kaedah Mutex.Lock() dan Mutex.Unlock(). Laluan pantas bermakna apabila status kunci tidak diduduki, kunci boleh diperolehi dengan cepat atau kunci boleh dilepaskan dengan cepat melalui CAS. Laluan perlahan bermakna apabila status kunci diduduki, goroutine semasa perlu ditambahkan pada baris gilir menunggu dan kaedah sema.acquire() dipanggil untuk tidur atau bangunkan goroutin lain dalam baris gilir menunggu.
3. Salah faham dalam penggunaan Mutex
Di Golang, Mutex ialah mekanisme penyegerakan yang sangat biasa digunakan, tetapi semasa penggunaan, terdapat beberapa salah faham yang perlu kita elakkan.
Jika goroutine cuba melepaskan Mutex yang tidak dipegangnya, program akan menimbulkan panik. Kunci Mutex adalah untuk memastikan akses yang saling eksklusif kepada sumber yang dikongsi Jika mana-mana goroutine boleh melepaskan kunci, maka eksklusiviti bersama tidak boleh dijamin.
Kunci Mutex ialah jenis penunjuk Jika anda perlu menyalin pembolehubah kunci, anda harus menggunakan salinan penunjuk. Jika tidak, ia akan mengakibatkan dua kejadian Mutex yang tidak berkaitan berkongsi keadaan yang sama, yang mungkin membawa kepada tingkah laku yang tidak dijangka.
Dalam pengaturcaraan serentak, persaingan bebas untuk kunci bermakna sebelum satu goroutine melepaskan kunci, goroutine lain akan terus Cuba memperoleh kunci dan bukannya menunggu dalam barisan menunggu. Ini akan membawa kepada pembaziran sumber CPU, dan keadaan ini harus dielakkan sebaik mungkin.
Ringkasnya, kunci ialah alat yang berkuasa untuk melindungi sumber yang dikongsi dan memainkan peranan yang sangat penting dalam pengaturcaraan serentak. Melalui artikel ini, kami memahami prinsip pelaksanaan asas Mutex, serta beberapa salah faham yang perlu diberi perhatian apabila menggunakan Mutex. Dalam pembangunan sebenar, kita harus menggunakan sepenuhnya kelebihan Mutex untuk mengelakkan pelbagai masalah yang mungkin timbul dalam pengaturcaraan serentak.
Atas ialah kandungan terperinci pelaksanaan asas Golang mutex. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!