Middle+
Πώς λειτουργεί ένα mutex στις κορουτίνες;
sobes.tech AI
Απάντηση από AI
Ένα mutex (Mutual Exclusion) στις coroutine παρέχει έναν μηχανισμό αμοιβαίας αποκλεισμού για την προστασία κοινών πόρων από ταυτόχρονη πρόσβαση από πολλές coroutine.
Αρχή λειτουργίας:
- Απόκτηση mutex: Η coroutine που θέλει να αποκτήσει πρόσβαση στον προστατευόμενο πόρο καλεί τη μέθοδο
lock(). - Μπλοκάρισμα: Αν το mutex είναι ελεύθερο, η coroutine το αποκτά χωρίς να μπλοκάρει και συνεχίζει την εκτέλεση. Αν το mutex είναι κατειλημμένο από άλλη coroutine, η καλούσα coroutine αναστέλλεται μέχρι να ελευθερωθεί το mutex.
- Απελευθέρωση mutex: Μετά το τέλος της εργασίας με τον προστατευόμενο πόρο, η coroutine καλεί τη μέθοδο
unlock()για να ελευθερώσει το mutex.
Βασικά χαρακτηριστικά στις coroutine:
lock()μη μπλοκαριστικό (όταν αποκτά ελεύθερο mutex): Σε αντίθεση με τα παραδοσιακά νήματα, όπου τοlock()μπορεί να μπλοκάρει ολόκληρο το νήμα, στις coroutine, αν το mutex είναι ελεύθερο, η απόκτησή του γίνεται χωρίς μπλοκάρισμα.- Αναστολή coroutine (όταν το mutex είναι κατειλημμένο): Αν το mutex είναι κατειλημμένο, η καλούσα coroutine δεν μπλοκάρει το νήμα, αλλά αναστέλλεται μέχρι να ελευθερωθεί. Αυτό απελευθερώνει το νήμα για την εκτέλεση άλλων coroutine.
- Λειτουργία επέκτασης
withLock: Βολικός τρόπος χρήσης του mutex, που το αποκτά και το απελευθερώνει αυτόματα, ακόμα και αν προκύψει εξαίρεση μέσα στο μπλοκ.
Παράδειγμα χρήσης:
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
val mutex = Mutex()
var counter = 0
suspend fun incrementCounter() {
mutex.withLock {
// Κρίσιμη ενότητα - προστατευόμενος πόρος
counter++
delay(10) // Προσομοίωση εργασίας
println("Counter: $counter")
} // Το mutex απελευθερώνεται αυτόματα εδώ
}
fun main() = runBlocking {
repeat(100) {
launch {
incrementCounter()
}
}
delay(1000)
}
Σε αυτό το παράδειγμα, το incrementCounter είναι μια κρίσιμη ενότητα που τροποποιεί τον κοινό πόρο counter. Το mutex διασφαλίζει ότι μόνο μια coroutine έχει πρόσβαση σε αυτήν την ενότητα κάθε φορά, αποτρέποντας καταστάσεις αγώνα. Η χρήση του withLock απλοποιεί τη διαχείριση του mutex.