Ce face sync.Mutex.TryLock
mu.TryLock() încuie mutexul și returnează true dacă era liber. Dacă alt goroutine îl ține, nu așteaptă, ci returnează imediat false. Când a returnat true, trebuie să apelezi Unlock, ca după Lock.
La sync.RWMutex, TryLock încearcă blocarea pentru scriere, iar TryRLock pe cea pentru citire (reușește dacă nu scrie nimeni).
Documentația Go avertizează că folosirile corecte sunt rare: de obicei e mai bine să aștepți cu Lock. Un caz potrivit este o sarcină pe care o sari dacă rulează deja, ca în al doilea exemplu.
Ce returnează
true dacă lacătul a fost obținut, false dacă era ocupat.
Exemple
Exemplul 1: Liber sau ocupat
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
mu.Lock()
fmt.Println("TryLock cât e ocupat:", mu.TryLock())
mu.Unlock()
if mu.TryLock() {
fmt.Println("TryLock după Unlock: true")
mu.Unlock()
}
var rw sync.RWMutex
rw.RLock()
fmt.Println("TryRLock cu un cititor activ:", rw.TryRLock())
fmt.Println("TryLock cu cititori activi: ", rw.TryLock())
rw.RUnlock()
rw.RUnlock()
fmt.Println("TryLock după RUnlock: ", rw.TryLock())
rw.Unlock()
}
Rezultat
TryLock cât e ocupat: false
TryLock după Unlock: true
TryRLock cu un cititor activ: true
TryLock cu cititori activi: false
TryLock după RUnlock: true
Exemplul 2: Sari peste o sarcină care rulează deja
Raportul se generează o singură dată; cererile care vin cât timp rulează nu așteaptă, ci primesc un mesaj.
package main
import (
"fmt"
"sync"
"time"
)
var generare sync.Mutex
func genereazaRaport() string {
if !generare.TryLock() {
return "raportul se generează deja, revino mai târziu"
}
defer generare.Unlock()
time.Sleep(300 * time.Millisecond)
return "raport generat"
}
func main() {
rezultate := make([]string, 2)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
rezultate[0] = genereazaRaport()
}()
time.Sleep(50 * time.Millisecond) // a doua cerere vine în timpul primei
rezultate[1] = genereazaRaport()
wg.Wait()
fmt.Println("Cererea 1:", rezultate[0])
fmt.Println("Cererea 2:", rezultate[1])
fmt.Println("Cererea 3:", genereazaRaport())
}
Rezultat
Cererea 1: raport generat
Cererea 2: raportul se generează deja, revino mai târziu
Cererea 3: raport generat
Greșeli frecvente
- Faci o buclă
for !mu.TryLock() {}ca să „aștepți activ”. Consumă procesorul degeaba; foloseșteLock(). - Apelezi
Unlockși cândTryLocka returnatfalse. Descuierea unui mutex pe care nu îl ții oprește programul.
Comenzi înrudite
sync.Mutex: Lacăt de excludere reciprocă: doar un goroutine pe rând poate rula codul dintre Lock() și Unlock().sync.RWMutex: Lacăt pentru citire și scriere: mai mulți cititori pot lucra deodată (RLock), dar un scriitor lucrează singur (Lock).