Sobes.tech
Middle

Ի՞նչ է մյուտեքսը, ինչ տեսակ մյուտեքսներ կան և ինչպես օգտագործել դրանք։

sobes.tech AI

Պատասխան AI-ից

Մյուտեքս (անգլ. MUTual EXclusion) — դա սինխրոնիզացիայի primitives է, որը օգտագործվում է բաժանվող ռեսուրսի բացառիկ մուտքը ապահովելու համար մրցակցող գորուտինների միջև։ Այն երաշխավորում է, որ ցանկացած պահի միայն մեկ գորուտին կարող է տիրապետել մյուտեքսին և համապատասխանաբար մուտք գործել պաշտպանված տվյալները։

Go-ում sync փաթեթը տրամադրում է երկու հիմնական մյուտեքսների տեսակներ՝

  • sync.Mutex: Ստանդարտ մյուտեքս։ Պատրաստում է Lock() և Unlock() մեթոդներ։ Եթե մյուտեքսը արդեն փակ է, Lock() կանչը բլոկավորում է ընթացիկ գորուտինին մինչև այն բացվի։ Unlock() բացում է մյուտեքսը։

    var mu sync.Mutex
    var counter int
    
    func increment() {
        mu.Lock() // Բլոկավորում մուտքը counter-ին
        counter++
        mu.Unlock() // Բացում մուտքը
    }
    
  • sync.RWMutex: Մյուտեքս ընթերցման/գրելու համար։ Ինքը թույլ է տալիս միաժամանակ մի քանի գորուտինների ընթերցել պաշտպանված ռեսուրսը, բայց միայն մեկին գրել։ Պատրաստում է Lock(), Unlock() (գրելու համար), RLock() և RUnlock() (ընթերցման համար) մեթոդներ։

    var rwMu sync.RWMutex
    var data []int
    
    func readData() {
        rwMu.RLock() // Բլոկավորում ընթերցման համար
        // Կարդում data
        fmt.Println(data)
        rwMu.RUnlock() // Բացում ընթերցումը
    }
    
    func writeData(val int) {
        rwMu.Lock() // Բլոկավորում գրելու համար
        // Գրանցում data-ում
        data = append(data, val)
        rwMu.Unlock() // Բացում գրառումը
    }
    

Մյուտեքսների օգտագործումը անհրաժեշտ է ռասային պայմանների կանխարգելման համար, երբ միաժամանակ մի քանի գորուտիններ փորձում են փոփոխել նույն տվյալները, ինչը կարող է հանգեցնել անսպասելի արդյունքների։

Օգտագործման կանոններ՝

  1. Կոչել Lock()՝ պաշտպանված ռեսուրսին մուտք գործելուց առաջ։
  2. Կոչել Unlock()՝ մուտքի ավարտից հետո։ Առաջարկվում է օգտագործել defer mu.Unlock()՝ բացելու համար նույնիսկ պանիկի դեպքում։
  3. Չի կարելի կրկին փակել արդեն փակ մյուտեքսը նույն գորուտինից։
  4. Չի կարելի բացել անփակ մյուտեքսը։
  5. Երբ օգտագործում եք RWMutex, օգտագործեք RLock()/RUnlock() ընթերցման համար և Lock()/Unlock() գրելու համար։
  6. Մյուտեքսները չպետք է պատճենվեն առաջին օգտագործումից հետո։ Դրանք փոխանցվում են հղումով կամ ցուցիչով։

Օրինակ defer օգտագործման:

func safeIncrement() {
    mu.Lock()
    defer mu.Unlock() // Գаранտիա է բացումը
    counter++
}