Livelock (penguncian aktif) — adalah situasi dalam pemrograman multi-thread ketika thread tidak terkunci, tetapi tanpa henti bereaksi terhadap tindakan satu sama lain tanpa melakukan pekerjaan yang berguna. Menurut Baeldung (Java Concurrency Guide, 2024), pada Livelock thread terus-menerus mengubah status sebagai respons terhadap status thread tetangga, tetapi tidak ada yang mencapai tujuan. Berbeda dengan Deadlock, Livelock mengonsumsi 100% CPU, yang dengan cepat menguras baterai perangkat seluler.
Utama
Livelock (penguncian aktif) — adalah situasi dalam sistem multi-thread di mana thread tidak terkunci tetapi juga tidak melakukan pekerjaan yang berguna. Setiap thread menemukan bahwa tidak dapat melanjutkan pekerjaan dan mencoba memperbaikinya, tetapi tindakannya memicu reaksi yang sama pada thread lain. Akibatnya, sistem tanpa henti beralih antar status tanpa mencapai kemajuan.
Analogi klasik Livelock — dua orang bertemu di koridor sempit. Masing-masing mencoba memberi jalan dengan menyingkir, tetapi keduanya secara bersamaan melakukan gerakan yang sama dan kembali berhadapan. Mereka tidak diam di tempat (itu akan menjadi Deadlock), tetapi bergerak aktif dan tetap tidak bisa berpisah. Dalam pemrograman, ini sesuai dengan thread yang terus-menerus melepaskan dan merebut kembali sumber daya.
Dalam pengembangan seluler, Livelock sangat berbahaya karena tidak terlihat oleh pengguna: aplikasi tidak hang, antarmuka tidak terkunci, tetapi baterai terkuras 2-3 kali lebih cepat karena 100% beban CPU oleh thread latar belakang. Menurut pengujian Google (Android Battery Optimization, 2023), Livelock di Service latar belakang dapat mengurangi waktu kerja perangkat hingga 40%.
Livelock terjadi ketika beberapa thread menggunakan strategi reaksi konflik yang sama. Jika Thread A tidak dapat memperoleh sumber daya dan melepaskan sumber daya saat ini, dan Thread B melakukan hal yang sama secara bersamaan, keduanya mengulangi siklus — dan situasi berulang tanpa henti. Ini sangat khas untuk algoritma dengan TryLock dan pelepasan otomatis saat gagal.
Ketika thread menggunakan penundaan tetap sebelum percobaan ulang, mereka dapat memasuki siklus sinkron. Jika kedua thread menunggu waktu yang sama, mereka akan kembali mencoba memperoleh sumber daya secara bersamaan dan melepaskannya secara bersamaan. Masalah diselesaikan dengan menggunakan exponential backoff dengan komponen acak (jitter), seperti dalam algoritma CSMA/CD di Ethernet.
Dalam pengembangan seluler, Livelock sering terjadi pada implementasi antrian tugas yang tidak benar. Misalnya, ketika thread pekerja menyelesaikan pemrosesan pesan, tetapi karena logika prioritas, terus-menerus menyerahkan kendali ke thread pekerja lain yang melakukan hal yang sama. Situasi seperti ini tipikal untuk ThreadPoolExecutor kustom dengan kebijakan RejectedExecutionHandler yang tidak standar.
Mari kita lihat situasi ketika dua thread menggunakan TryLock dan melepaskan sumber daya saat gagal. Penguncian aktif terjadi karena kedua thread menerapkan logika yang sama dan mengulangi percobaan secara sinkron.
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.TimeUnit
class LivelockWorker(private val name: String,
private val lock1: ReentrantLock,
private val lock2: ReentrantLock) {
fun execute() {
while (true) {
if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) {
if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) {
println("$name — selesai!")
lock2.unlock()
lock1.unlock()
return
} else {
lock1.unlock() // melepaskan dan mengulangi
}
}
Thread.sleep(50) // penundaan tetap — faktor kunci Livelock
}
}
}
Jika dua instance LivelockWorker dijalankan dengan urutan perolehan lock1 dan lock2 yang berbeda, mereka akan memasuki penguncian aktif. Masing-masing akan memperoleh sumber daya pertama, tidak mendapatkan yang kedua, melepaskan yang pertama, menunggu 50 ms dan mengulangi — tanpa henti, menghabiskan CPU. Perbaikan — menambahkan komponen acak pada penundaan (jitter) dan membatasi jumlah percobaan ulang.
Versi yang diperbaiki menggunakan exponential backoff dengan jitter acak. Setelah setiap percobaan gagal, waktu tunggu meningkat dengan penambahan faktor acak, yang menghancurkan sinkronisasi antar thread.
fun executeWithBackoff() {
var delay = 10L
var attempts = 0
while (attempts < 5) {
if (lock1.tryLock(delay, TimeUnit.MILLISECONDS)) {
if (lock2.tryLock(delay, TimeUnit.MILLISECONDS)) {
println("Berhasil!")
lock2.unlock(); lock1.unlock()
return
}
lock1.unlock()
}
delay = (delay * 2 + (0..50).random())
attempts++
}
println("Tidak berhasil setelah 5 percobaan")
}
Meskipun memiliki kemiripan luar, Livelock dan Deadlock memiliki mekanisme dan konsekuensi yang berbeda secara fundamental. Pada Deadlock, thread terkunci dan tidak mengonsumsi CPU — aplikasi hanya hang. Pada Livelock, thread aktif, mengonsumsi 100% CPU, tetapi tidak melakukan pekerjaan yang berguna. Pemilihan strategi eliminasi tergantung pada penentuan jenis penguncian yang tepat.
| Parameter | Deadlock | Livelock |
|---|---|---|
| Status thread | BLOCKED / WAITING | RUNNABLE |
| Konsumsi CPU | Minimal | Tinggi (90-100%) |
| Konsumsi baterai | Rendah | Tinggi |
| Deteksi | Thread Dump | CPU Profiler + analisis visual |
| Penyebab tipikal | Urutan perolehan kunci yang berbeda | Strategi reaksi konflik yang sama |
| Perbaikan | Hierarki kunci | Retry limit + exponential backoff |
Dalam pengembangan seluler, perbedaan praktisnya sangat besar. Deadlock menyebabkan ANR dan restart aplikasi — terdeteksi dan dilaporkan melalui Google Play Console. Livelock tidak terdeteksi: aplikasi tampak berfungsi, tetapi baterai habis dalam satu jam, dan pengguna cukup menghapus aplikasi. Menurut Firebase Analytics (App Retention Report, 2024), 68% pengguna menghapus aplikasi jika aplikasi tersebut mengonsumsi baterai secara berlebihan di latar belakang.
Deteksi Livelock lebih sulit daripada Deadlock karena sistem tidak memberikan sinyal yang jelas — tidak ada pengecualian, tidak ada ANR, tidak ada pesan kesalahan. Metode diagnostik utama — CPU Profiler di Android Studio. Jika thread terus-menerus dalam status RUNNABLE tetapi tidak melakukan operasi input-output atau kalkulasi yang berguna — ini adalah kecurigaan Livelock.
Tanda tambahan — konsumsi baterai abnormal saat aplikasi tidak aktif. Android Battery Historian (alat dari Android SDK) membuat grafik konsumsi energi per komponen. Jika CPU Wakelock dipertahankan tanpa alasan yang jelas — sebaiknya jalankan Method Tracing dan analisis stack panggilan thread yang mencurigakan.
Pada tingkat kode, logging percobaan ulang dengan threadId dan waktu membantu. Jika log menunjukkan ribuan percobaan ulang per detik tanpa satu pun keberhasilan — ini adalah Livelock. Disarankan untuk mengimplementasikan circuit breaker mirip Hystrix atau penghitung retry dengan ambang pemicu yang, ketika terlampaui, menonaktifkan operasi dan memberi tahu pengembang melalui Crashlytics.
Cara paling sederhana dan paling andal — membatasi jumlah percobaan perolehan sumber daya. Jika setelah N percobaan operasi gagal, thread masuk ke status kesalahan dan memberi tahu pengguna. N dipilih secara empiris: untuk aplikasi seluler biasanya 3-5 percobaan. Ini sepenuhnya menghilangkan Livelock tanpa henti dengan mengorbankan pemicuan palsu yang jarang terjadi pada beban tinggi.
Alih-alih penundaan tetap antar percobaan, digunakan jeda yang meningkat secara eksponensial dengan komponen acak. Rumus: delay = min(baseDelay * 2^attempt, maxDelay) + random(0, jitter). Pendekatan ini tidak hanya menghancurkan sinkronisasi thread, tetapi juga mengurangi beban sistem secara keseluruhan pada konkurensi tinggi. Digunakan dalam algoritma protokol jaringan dan direkomendasikan oleh Google untuk logika percobaan ulang Firebase Realtime Database.
Menetapkan strategi yang berbeda ke thread yang berbeda menghilangkan penyebab Livelock — reaksi yang sama terhadap konflik. Misalnya, thread dengan prioritas tinggi mendapatkan sumber daya tanpa melepaskan, dan thread prioritas rendah melepaskan dan menunggu. Dalam pengembangan seluler, thread UI dapat memiliki prioritas dalam perolehan kunci, dan thread pekerja latar belakang dapat menggunakan TryLock dengan timeout.
Dalam beberapa arsitektur, Livelock dicegah pada tingkat desain: pelepasan sumber daya hanya dalam satu arah. Misalnya, jika Thread A selalu menyerahkan kendali ke Thread B melalui saluran tetap (Channel), dan B tidak pernah mencoba mengembalikan kendali ke A — siklus reaksi tidak mungkin terjadi. Arsitektur pipeline dengan tahap pemrosesan satu arah di Android CameraX dan MediaPipe sepenuhnya menghilangkan Livelock antar tahap yang berdekatan.
Pertanyaan yang sering diajukan
Loop tak terbatas tidak bergantung pada faktor eksternal dan mengulangi satu operasi tanpa interaksi dengan thread lain. Livelock selalu merupakan reaksi terhadap tindakan thread lain: thread mengubah perilaku sebagai respons terhadap status thread tetangga, menciptakan umpan balik tertutup. Thread Dump dalam kasus Livelock menunjukkan pergantian konteks yang konstan.
Dalam basis data, Livelock terjadi ketika transaksi terus-menerus ditunda karena penguncian oleh transaksi lain. Misalnya, DBMS menggunakan algoritma wait-die: jika transaksi dengan waktu mulai lebih kecil bertentangan dengan yang lebih baru, transaksi tersebut dibatalkan dan dimulai ulang, tetapi setiap kali mengalami konflik yang sama. Ini diselesaikan dengan randomized restart delay.
Dalam beberapa sistem, Livelock lebih diutamakan daripada Deadlock, karena thread tetap aktif dan dapat mendeteksi masalah. Misalnya, dalam algoritma penguncian optimis (optimistic locking), perilaku mirip livelock diizinkan jika retry limit menjamin penyelesaian akhir. Ini adalah kompromi antara kinerja dan jaminan kemajuan.
Livelock sangat sulit direproduksi dalam pengujian, karena memerlukan kebetulan waktu thread yang tepat. Pengujian unit dijalankan secara deterministik dan jarang mendeteksi penguncian aktif. Disarankan untuk menggunakan Stress Testing dengan eksekusi berulang di bawah beban dan pemantauan konsumsi CPU di profiler.
Di server, Livelock menyebabkan degradasi kinerja dan timeout, tetapi server dapat diskalakan secara horizontal. Di Android, Livelock menguras baterai dan memanaskan perangkat, menciptakan pengalaman pengguna yang lebih buruk. Selain itu, pada perangkat seluler jumlah inti CPU terbatas, sehingga Livelock lebih cepat menyebabkan ketidakmampuan seluruh sistem.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga