Rumah  >  Artikel  >  pembangunan bahagian belakang  >  pelaksanaan asas Golang mutex

pelaksanaan asas Golang mutex

WBOY
WBOYasal
2023-05-10 19:04:05673semak imbas

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.

  1. Groutine yang memanggil kaedah Unlock() mestilah goroutine yang memegang Mutex

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.

  1. Jangan salin Mutex

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.

  1. Cuba elakkan persaingan percuma untuk kunci

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!

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