Mutex dan Semaphore untuk Status Bersama
Lindungi status mutable bersama menggunakan Mutex dan batasi konkurensi dengan Semaphore.
Mutex dan Semaphore untuk Status Bersama adalah pelajaran Kotlin Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Kotlin Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Kotlin Academy mencakup 4 pelajaran total.
Masalah Status Bersama
Coroutine pada beberapa utas dapat merusak status berubah-ubah yang digunakan bersama. Tanpa sinkronisasi, penambahan secara bersamaan menghasilkan nilai yang salah.
import kotlinx.coroutines.*
fun main() = runBlocking {
var counter = 0
val jobs = List(1000) {
launch(Dispatchers.Default) { counter++ } // race condition!
}
jobs.forEach { it.join() }
println("Expected 1000, got: $counter") // likely wrong
}Dasar-Dasar Saling Kunci
Mutex adalah kunci eksklusi bersama untuk coroutine. Kunci ini menangguhkan, bukan memblokir, pemanggil hingga kunci tersedia.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val mutex = Mutex()
var counter = 0
val jobs = List(1000) {
launch(Dispatchers.Default) {
mutex.withLock { counter++ } // safe
}
}
jobs.forEach { it.join() }
println("Counter: $counter") // 1000
}Ekstensi withLock
mutex.withLock { ... } memperoleh kunci, menjalankan blok, lalu melepaskannya — bahkan saat terjadi pengecualian atau pembatalan.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val mutex = Mutex()
var list = mutableListOf<Int>()
List(10) {
launch {
mutex.withLock {
list.add(it)
}
}
}.forEach { it.join() }
println(list.sorted())
}lock / unlock Secara Manual
Anda dapat langsung memanggil lock() dan unlock() untuk memperoleh kendali yang lebih terperinci, tetapi sebaiknya gunakan withLock agar tidak lupa membuka kunci.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val mutex = Mutex()
mutex.lock()
try {
println("Critical section")
} finally {
mutex.unlock() // must always release
}
}Mutex Tidak Dapat Dipakai Kembali Secara Rekursif
Mutex Kotlin tidak dapat dipakai kembali secara rekursif. Memanggil lock() lagi dari coroutine yang sama akan menyebabkan kebuntuan. Gunakan penghitung atau ubah struktur kode untuk menghindari penguncian bertingkat.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val mutex = Mutex()
// This deadlocks:
// mutex.withLock { mutex.withLock { println("never") } }
mutex.withLock {
println("Acquired once — safe")
}
}Dasar-Dasar Semafor
Semaphore(n) memungkinkan hingga n coroutine berjalan secara bersamaan. Ini seperti sistem tiket dengan n slot.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val semaphore = Semaphore(3) // max 3 concurrent
List(10) { i ->
launch {
semaphore.withPermit {
println("Concurrent task $i"); delay(100)
}
}
}.forEach { it.join() }
}Ekstensi withPermit
semaphore.withPermit { ... } memperoleh izin, menjalankan blok, lalu melepaskannya — ini adalah padanan aman untuk coroutine dari upaya memperoleh izin semafor.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
fun main() = runBlocking {
val sem = Semaphore(2)
val results = mutableListOf<String>()
List(5) { i ->
launch {
sem.withPermit {
delay(50)
synchronized(results) { results.add("task-$i") }
}
}
}.forEach { it.join() }
println(results)
}Pembatasan Laju dengan Semafor
Gunakan semafor untuk membatasi laju panggilan API secara bersamaan — batasi hingga N permintaan pada satu waktu.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
val apiSemaphore = Semaphore(5) // max 5 concurrent requests
suspend fun callApi(id: Int): String {
return apiSemaphore.withPermit {
delay(100) // simulate network
"Response-$id"
}
}
fun main() = runBlocking {
val results = (1..20).map { async { callApi(it) } }.awaitAll()
println("Got ${results.size} responses")
}Perbedaan Saling Kunci dan Semafor
Mutex: semafor biner dengan satu izin, untuk akses eksklusif. Semaphore(n): n izin, untuk konkurensi terbatas. Gunakan Mutex untuk melindungi sumber daya; gunakan Semaphore untuk membatasi paralelisme.
import kotlinx.coroutines.sync.*
// Mutex = Semaphore(1) for exclusive access
// Semaphore(n) = n-way concurrency limit
val exclusive = Mutex() // one at a time
val limited = Semaphore(3) // three at a time
fun main() { println("Mutex for exclusion; Semaphore for rate limiting") }Penghitung Atomik dengan Saling Kunci
Implementasikan kelas penghitung yang aman untuk utas dengan menggunakan Mutex untuk melindungi operasi penambahan dan pembacaan.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
class AtomicCounter {
private val mutex = Mutex()
private var count = 0
suspend fun increment() = mutex.withLock { count++ }
suspend fun get() = mutex.withLock { count }
}
fun main() = runBlocking {
val counter = AtomicCounter()
List(100) { launch { counter.increment() } }.forEach { it.join() }
println("Count: ${counter.get()}")
}Alternatif: Dispetser Satu Utas
Alih-alih menggunakan saling kunci, batasi status yang dapat berubah pada dispetser satu utas. Hanya satu coroutine yang berjalan pada dispetser tersebut dalam satu waktu, sehingga aksesnya secara bawaan aman.
import kotlinx.coroutines.*
fun main() = runBlocking {
val singleThread = newSingleThreadContext("CounterThread")
var counter = 0
List(1000) {
launch(singleThread) { counter++ }
}.forEach { it.join() }
println("Counter: $counter") // 1000, no mutex needed
singleThread.close()
}Pemeriksaan Singkat
Apa perbedaan utama antara Mutex dan Semaphore?
Ringkasan
Mutex menyediakan akses eksklusif ke status bersama — utamakan withLock. Semaphore(n) membatasi konkurensi hingga n. Keduanya menangguhkan, bukan memblokir, coroutine yang sedang menunggu. Untuk kasus sederhana, dispetser satu utas sering kali lebih mudah dipahami.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Mutex dan Semaphore untuk Status Bersama” gratis?
Ya — teks lengkap “Mutex dan Semaphore untuk Status Bersama” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Kotlin Academy, upgrade ke CoddyKit PRO. Kursus Kotlin Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Mutex dan Semaphore untuk Status Bersama”?
Lindungi status mutable bersama menggunakan Mutex dan batasi konkurensi dengan Semaphore. Kamu berlatih Kotlin Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Kotlin Academy?
Tidak diperlukan pengalaman sebelumnya. Kotlin Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Mutex dan Semaphore untuk Status Bersama” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Kotlin Academy ini?
Ya. Setiap pelajaran Kotlin Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Dasar Channel: send, receive, dan close
- Tipe Channel: Rendezvous, Buffered, Conflated, Unlimited
- Mutex dan Semaphore untuk Status Bersama
- Actor dan Pengelolaan Status Terstruktur