Topik wawancara representatif

Bagaimana Cara Anda Mencegah, Mendeteksi, dan Memulihkan Diri dari Deadlock?

UmumSedang
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Layanan transfer terkadang mengalami freeze: thread A memegang lock untuk akun 42 dan menunggu akun 84, sedangkan thread B memegang akun 84 dan menunggu akun 42. Apakah ini deadlock? Jelaskan empat kondisi yang diperlukan dan rancang pencegahan, deteksi, pemulihan, serta validasinya.

Prompt dan Konteks yang Berlaku

Layanan transfer terkadang mengalami freeze: thread A memegang lock untuk akun 42 dan menunggu akun 84, sedangkan thread B memegang akun 84 dan menunggu akun 42. Tidak ada thread yang melepaskan lock pertamanya. Apakah ini deadlock? Jelaskan empat kondisi yang diperlukan dan rancang pencegahan (prevention), deteksi (detection), pemulihan (recovery), serta validasi (validation).

Ini adalah pertanyaan umum rekayasa perangkat lunak dan sistem operasi untuk backend, sistem, infrastruktur, SRE, dan peran lain yang menulis kode konkuren. Materi wawancara bahasa Inggris dan Mandarin 2026 saat ini masih menanyakan secara terpisah mengenai definisi, empat kondisi yang diperlukan, dan strategi penanganannya. Artikel ini tidak mencantumkan atribusi perusahaan dan tidak mengklaim frekuensi wawancara yang tidak didukung bukti.

Akun 42 dan 84 adalah pengidentifikasi fiktif. Tugas ini lebih dari sekadar menghafal empat istilah. Jawaban yang kuat membedakan waktu tunggu yang lama dari siklus tunggu yang tidak dapat disederhanakan (irreducible wait cycle), kemudian menghubungkan teori tersebut dengan protokol penguncian (lock protocol), bukti runtime, pemulihan kegagalan, dan pengujian. Cakupan utamanya adalah mutex single-instance dan row lock database. Distributed lease, partisi jaringan, dan konsensus berada di luar jawaban pertama.

Apa yang Dinilai oleh Pewawancara

Sinyal pertama adalah apakah diagnosis menggunakan relasi tunggu (wait relationships). Penggunaan CPU yang rendah, permintaan yang mengalami time-out, atau dua thread yang terblokir menunjukkan kurangnya progres tetapi tidak membuktikan deadlock secara independen. Jawaban yang kuat membangun wait-for graph yang node-nodenya adalah thread atau transaksi dan edge-edgenya berarti "menunggu resource yang dimiliki oleh", lalu mencari adanya siklus.

Sinyal kedua adalah penggunaan yang akurat dari empat kondisi yang diperlukan: mutual exclusion, hold and wait, no preemption, dan circular wait. Keempatnya menjelaskan mengapa deadlock dapat terjadi. Menyebutkannya tanpa memetakan masing-masing ke alur transfer tetap dianggap sebagai respons hafalan.

Sinyal ketiga adalah strategi pencegahan dengan invariansi global yang dapat dibuktikan (provable global invariant). Pilihan praktisnya sering kali berupa total order yang stabil untuk setiap lock, yang diterapkan di setiap entry point. Menukar dua baris dalam satu fungsi saja tidak cukup. Batch job, refund, tool perbaikan, dan alur di masa mendatang dapat membuat siklus kembali jika ada yang memperoleh lock dalam urutan terbalik.

Terakhir, pewawancara mengevaluasi batasan pemulihan. Database dapat mendeteksi siklus dan melakukan rollback transaksi. Mutex in-process biasanya tidak dapat diambil secara paksa dengan aman lalu eksekusinya dilanjutkan, karena kode yang terinterupsi mungkin baru mengubah separuh dari suatu invariansi. Jawaban yang kuat memisahkan pencegahan, penghindaran (avoidance), deteksi, dan pemulihan, menyatakan biaya timeout, serta mereproduksi interleaving daripada hanya berharap uji beban (stress test) akan menemukannya.

Pertanyaan yang Perlu Diklarifikasi Sebelum Menjawab

  • Apakah semua resource berupa single-instance mutex? Siklus dalam wait-for graph pada resource single-instance membuktikan bahwa kelompok tersebut tidak dapat membuat progres. Jika suatu jenis resource memiliki beberapa instance, siklus dalam resource-allocation graph menunjukkan kemungkinan; instance yang tersedia dan kebutuhan yang tersisa masih berpengaruh.
  • Apakah lock bersifat reentrant? Memperoleh kembali non-reentrant lock pada thread yang sama dapat menyebabkan self-deadlock. Jika sumber dan tujuan adalah akun yang sama, lakukan deduplikasi sebelum mengunci daripada mengasumsikan pengurutan (sorting) akan menangani duplikat tersebut.
  • Apakah kedua perubahan akun berada dalam satu transaksi yang dapat di-rollback? Batasan transaksi dapat mengorbankan victim dan mencoba kembali. Alur yang telah mengirim pembayaran eksternal atau email memerlukan idempotency key atau post-commit outbox, bukan pengulangan buta (blind replay).
  • Bisakah setiap jalur perolehan (acquisition path) berbagi satu aturan pengurutan? Jika ya, prioritaskan pengurutan global. Jika komponen pihak ketiga atau resource lintas layanan tidak dapat mengikuti protokol tersebut, kurangi kepemilikan simultan, rancang ulang kepemilikan, atau terapkan deteksi dan rollback di sekitar batasan yang aman.
  • Berapa lama permintaan boleh menunggu, dan apa arti timeout? Lock timeout membatasi tail latency tetapi dapat menghentikan permintaan lambat yang sah. Penelepon perlu mengetahui apakah operasi tersebut dapat dicoba lagi (retryable), final, atau hasilnya tidak diketahui (outcome-unknown).
  • Fasilitas diagnostik apa yang disediakan oleh runtime? Manajemen thread JVM, view tunggu database, dan validator lock kernel mencakup kelas lock yang berbeda. Tidak adanya laporan dari satu alat tidak berarti aman dari asynchronous wait, virtual thread, atau resource eksternal.
  • Apakah critical section memanggil operasi jaringan, disk, atau yang dikendalikan pengguna? Dependensi yang tidak terbatas memperpanjang kepemilikan dan memperbesar pemblokiran. Pindahkan ke luar kecuali protokol konsistensi secara eksplisit mengharuskan penantian tersebut dan menangani kegagalannya.

Kerangka Jawaban 30 Detik

"Ini adalah deadlock: A menunggu B melepaskan 84, sementara B menunggu A melepaskan 42, sehingga wait-for graph berisi A → B → A. Kasus ini memiliki mutual exclusion, hold and wait, no preemption, dan circular wait. Saya akan mendeduplikasi ID akun dan memperoleh semua lock akun dalam satu urutan naik yang stabil (stable ascending order), melepaskannya secara terbalik, yang memutus circular wait berdasarkan protokol. Di lingkungan produksi, saya akan mengonfirmasi siklus dari data tunggu thread atau database. Victim database di-rollback dan dicoba kembali dengan batas tertentu; untuk deadlock in-process, saya mempertahankan diagnostik dan memulihkan hanya pada batasan state yang aman. Pengujian barrier membuat interleaving lama menjadi deterministik dan memverifikasi bahwa versi yang terurut mempertahankan invariansi saldo."

Jawaban yang lengkap harus menambahkan mengapa pengurutan meniadakan siklus, mengapa timeout bukan merupakan bukti, penantian apa saja yang dicakup oleh detektor, dan apakah pemulihan dapat menduplikasi efek samping eksternal.

Jawaban Mendalam Langkah demi Langkah

Langkah 1: Buktikan siklus tunggu alih-alih mendiagnosis dari gejala semata

Representasikan state runtime sebagai wait-for graph. Thread A memegang lock 42 dan meminta 84 yang dimiliki B, jadi tambahkan A → B. Thread B memegang 84 dan meminta 42 yang dimiliki A, jadi tambahkan B → A. Masing-masing thread hanya melepaskan lock pertamanya setelah memperoleh lock kedua. Tidak ada node dalam siklus yang dapat selesai lebih dulu, sehingga kelompok tersebut tidak dapat membuat progres sendiri.

Diagnosis produksi memerlukan informasi pemilik, penunggu, dan stack trace dari momen yang kira-kira sama. Satu snapshot thread mungkin hanya menangkap perebutan resource (contention) yang tidak berbahaya. Snapshot berulang dengan stack dan edge yang sama memberikan bukti yang lebih kuat. Penantian yang lama tetapi normal tidak memiliki return edge: A mungkin menunggu B sementara B sedang berjalan dan pada akhirnya melepaskan resource-nya. Menyebut setiap lock yang lambat sebagai deadlock adalah kesalahan diagnosis latensi kapasitas atau dependensi sebagai bug protokol penguncian.

Kesimpulan graf memiliki batasan model. Ketika setiap mutex memiliki satu pemilik, siklus tunggu sudah cukup untuk membuktikan deadlock di antara thread-thread tersebut. Ketika suatu kategori resource memiliki beberapa instance, siklus dalam resource-allocation graph menunjukkan risiko dan bukan bukti pasti; instance luar mungkin dilepaskan dan memungkinkan partisipan untuk melanjutkan. Analisis kemudian memerlukan data permintaan yang tersedia, yang dialokasikan, dan sisa maksimum yang dibutuhkan.

Langkah 2: Petakan empat kondisi yang diperlukan ke dalam kode

Keempat kondisi tersebut terlihat konkret dalam transfer ini:

  1. Eksklusi mutual (mutual exclusion): satu thread pada satu waktu memegang write lock akun.
  2. Menahan sambil menunggu (hold and wait): A memegang 42 saat meminta 84; B memegang 84 saat meminta 42.
  3. Tanpa preemsi (no preemption): runtime tidak mengambil lock akun dari pemiliknya secara paksa dengan aman; pemiliklah yang melepaskannya.
  4. Penantian melingkar (circular wait): A menunggu B dan B menunggu A.

Setiap kondisi ada saat deadlock ini terjadi, dan memutus salah satu saja akan mencegah kelas masalah ini. Jangan menganggap "sistem menggunakan mutex" atau "kode melakukan nested locking" sebagai bukti deadlock aktif. Kondisi yang diperlukan hanya menjelaskan apa yang memungkinkan terjadinya deadlock; state runtime tetap memerlukan siklus yang tidak dapat disederhanakan.

Mutual exclusion mungkin melindungi invariansi saldo, sehingga menghapusnya dan membiarkan race condition pada shared state bukanlah solusi. Preemption yang aman juga sulit diterapkan untuk critical section dalam memori yang biasa. Sistem rekayasa lebih sering menghilangkan circular wait atau, pada batasan yang mendukung rollback, mendeteksi dan membatalkan satu transaksi.

Langkah 3: Hilangkan circular wait dengan urutan lock global

Definisikan total order untuk setiap lock yang mungkin dipegang bersamaan, seperti tingkatan jenis resource diikuti oleh ID resource. Jika hanya lock akun yang terlibat, urutkan berdasarkan ID akun. Lakukan deduplikasi terlebih dahulu untuk menangani transfer yang sumber dan tujuannya sama. Dapatkan lock secara berurutan, lakukan hanya validasi dan mutasi state di dalam critical section, lalu lepaskan dengan urutan terbalik.

Pseudocode netral-bahasa:

transfer(fromid, toid, amount): ids = unique(sortascending([fromid, to_id])) acquired = [] try: for id in ids: acquired.append(lock_account(id)) validateandapplytransfer(fromid, to_id, amount) finally: for lock in reverse(acquired): unlock(lock)

Argumen kebenarannya singkat. Jika thread yang memegang lock berperingkat lebih rendah hanya boleh menunggu lock berperingkat lebih tinggi, siklus tunggu akan mengharuskan peringkat meningkat secara ketat:

r1 < r2 < … < rn < r1

Urutan yang ketat tidak dapat kembali ke titik awalnya, sehingga circular wait menjadi mustahil. Pembuktian ini bergantung pada setiap alur yang mematuhi urutan yang sama. Mendapatkan lock berdasarkan urutan permintaan, urutan iterasi list, atau urutan pengembalian database pada satu jalur sampingan akan membatalkan invariansi tersebut.

Pelepasan secara terbalik membuat kepemilikan bersarang (nested ownership) lebih mudah dipahami tetapi bukan hal utama yang mencegah siklus. Aturan yang lebih penting adalah menghindari remote call, input pengguna, dan I/O tanpa batas saat memegang lock. Critical section yang panjang mungkin tidak mengalami deadlock, tetapi hal itu memperbesar contention, timeout, dan biaya pemulihan.

Langkah 4: Ketahui kapan strategi lain lebih sesuai

Meminta setiap resource sebelum melakukan pekerjaan memutus hold and wait, tetapi pemanggil harus mengetahui kumpulan lengkapnya terlebih dahulu. Kumpulan yang besar juga memperpanjang kepemilikan dan mengurangi konkurensi. Ini cocok untuk set lock yang kecil dan diketahui, serta kurang cocok ketika penelusuran menemukan resource secara bertahap.

Deadlock avoidance menanyakan apakah mengabulkan permintaan akan mempertahankan safe state. Banker's algorithm memerlukan permintaan maksimum di awal dan melacak resource yang tersedia, maksimum, dialokasikan, dan tersisa. Permintaan web dinamis jarang mengetahui setiap objek yang nantinya akan disentuh, sehingga algoritma ini berguna untuk menjelaskan safe state tetapi biasanya tidak disalin ke dalam kode aplikasi. Safe state menjamin adanya urutan penyelesaian. Unsafe state dapat menyebabkan deadlock tetapi belum tentu berada dalam kondisi deadlock.

Mengurangi shared mutable state, menetapkan satu pemilik, atau menggunakan concurrent container yang matang dapat menghilangkan jalur penguncian manual. Hal ini tidak membenarkan anggapan bahwa "arsitektur berbasis pesan tidak dapat mengalami deadlock". Dua antrean berbatas (bounded queues) dapat saling menunggu kapasitas satu sama lain, dan tugas-tugas dalam satu executor dapat menunggu hasil secara siklis. Alternatif tersebut tetap membutuhkan analisis wait graph.

Try-lock dan timeout adalah mekanisme pelarian yang lossy, bukan bukti dari protokol yang asiklik. Jika jalur timeout melakukan rollback pada state parsial dan melepaskan setiap lock yang dipegang, ini memutus hold and wait setelah ambang batas tercapai dan melenyapkan siklus ini. Permintaan tetap terhenti sebelum ambang batas, dan ambang batas yang terlalu pendek akan menggugurkan pekerjaan yang sah. Kedua belah pihak dapat mengalami timeout dan mencoba lagi secara bersamaan, menghasilkan livelock. Gunakan batas percobaan maksimum, randomized backoff, semantik idempoten, dan terminal error.

Langkah 5: Nyatakan apa yang sebenarnya dicakup oleh setiap detektor

JVM ThreadMXBean dapat menemukan siklus di antara platform thread yang menunggu object monitor atau ownable synchronizer dan mengembalikan ID-nya. Dokumentasi Java SE 25 menyatakan bahwa siklus yang berisi virtual thread tidak ditemukan oleh metode ini dan operasi ini ditujukan untuk pemecahan masalah, bukan kontrol sinkronisasi. Hasil null hanya membersihkan cakupan detektor tersebut.

lockdep kernel Linux mencatat dependensi perolehan yang diamati antar-kelas lock. Jika eksekusi mengekspos L1 → L2 dan L2 → L1, ini dapat melaporkan potensi inversi meskipun eksekusi saat ini tidak sampai mengalami freeze. Ini mendemonstrasikan bagaimana lingkungan pengembangan dan pengujian dapat memvalidasi protokol pengurutan; kode aplikasi tidak dapat mengasumsikan setiap runtime menawarkan validator yang sama.

PostgreSQL secara otomatis mendeteksi deadlock transaksi dan menggugurkan salah satu transaksi yang berpartisipasi sehingga transaksi lainnya dapat melanjutkan. Dokumentasinya menyebutkan bahwa korban (victim) sulit diprediksi, sehingga logika bisnis tidak boleh bergantung pada asumsi bahwa "permintaan yang lebih baru selalu kalah". PostgreSQL juga merekomendasikan urutan perolehan yang konsisten di seluruh aplikasi dan mencoba kembali transaksi yang dibatalkan jika pencegahan total tidak memungkinkan.

Sinyal produksi harus mencakup durasi tunggu lock, durasi penahanan lock, jumlah deadlock, transaksi yang di-rollback, upaya retry, dan kegagalan terminal. Catatan diagnostik harus mengorelasikan penunggu, pemilik, kelas lock, dan stack trace tanpa mencatat data akun lengkap, parameter kueri, atau payload sensitif.

Langkah 6: Pulihkan pada batasan konsistensi resource

Setelah database memilih victim, lakukan rollback pada seluruh transaksi, baca ulang state, dan eksekusi kembali. Jangan melanjutkan dari "setelah lock pertama". Batasi percobaan ulang dan tambahkan jeda acak (randomized delay). Jika permintaan duplikat dapat tiba, gunakan business idempotency key. Picu email, pengiriman pesan, atau pembayaran eksternal setelah commit melalui jalur idempoten seperti outbox pattern karena rollback database tidak dapat membatalkan efek samping yang telah dikeluarkan.

Ketika thread in-process macet pada mutex, penghentian paksa salah satunya dapat meninggalkan invariansi in-memory dalam kondisi setengah terbarui. Jalur pemulihan yang umum adalah mengambil thread dump dan metrik utama, kemudian membiarkan mekanisme supervisi me-restart proses atau instance yang state-nya dapat direkonstruksi dengan aman. Jika proses tersebut memiliki state unik yang tidak dapat dipulihkan, restart juga tidak aman; persistensi dan pemulihan perlu dirancang ulang.

Pemilihan victim dapat mempertimbangkan pekerjaan yang telah dilakukan, biaya rollback, prioritas, dan riwayat retry, tetapi kebenaran (correctness) adalah yang utama. Pemulihan memulihkan progres dan tidak menghilangkan penyebabnya. Tanpa memperbaiki urutan lock, traffic yang sama dapat mengalami deadlock kembali.

Langkah 7: Validasi perbaikan dengan interleaving deterministik

Jangan hanya mengandalkan uji konkurensi tinggi untuk mendapatkan keberuntungan. Tambahkan test barrier ke implementasi lama. A mencapai barrier setelah mengunci 42, dan B mencapainya setelah mengunci 84. Lepaskan keduanya untuk meminta lock kedua mereka. Watchdog harus menangkap kedua edge tunggu dalam batas waktu pengujian, membuktikan A → B → A daripada hanya mendeteksi mesin uji yang lambat.

Jalankan input terbalik yang sama terhadap implementasi yang telah diperbaiki. A dan B keduanya mencoba ID yang lebih rendah (42) terlebih dahulu. Salah satunya menunggu tanpa memiliki 84; pemenangnya memperoleh 84, menyelesaikannya, dan melepaskannya, setelah itu pihak yang lain melanjutkan. Verifikasi bahwa kedua permintaan menerima hasil yang valid sesuai kontrak, total saldo tidak berubah, dan tidak ada transfer yang dieksekusi dua kali.

Cakup juga:

  • ID sumber dan tujuan yang identik, membuktikan bahwa deduplikasi menghindari perolehan kedua dari non-reentrant lock;
  • tiga akun atau lebih dan beberapa jenis resource, membuktikan bahwa kunci pengurutan identik di semua jalur;
  • saldo tidak mencukupi, exception, pembatalan, dan kegagalan perolehan parsial, membuktikan bahwa finally melepaskan setiap lock yang diperoleh;
  • jalur batch, refund, dan perbaikan yang berjalan konkuren dengan transfer online, untuk menemukan inversi bypass;
  • deteksi database dan rollback victim, memvalidasi retry penuh, efek samping idempoten, dan batas retry;
  • soak test dengan beban perebutan resource tinggi (high-contention) yang diacak, yang terus-menerus memeriksa saldo, waktu tunggu lock, deadlock, dan starvation.

Pengujian deterministik menutup counterexample yang diketahui. Soak test mencari alur yang belum teridentifikasi. Keduanya diperlukan sebelum mengklaim bahwa protokol telah divalidasi.

Contoh Jawaban Berkualitas Tinggi

"Pertama-tama saya akan membuktikan bahwa ini lebih dari sekadar penantian yang lambat. A memiliki 42 dan menunggu 84 milik B, sehingga A → B. B memiliki 84 dan menunggu 42 milik A, sehingga B → A. Masing-masing single-instance mutex dilepaskan hanya setelah pemiliknya mendapatkan yang kedua, menjadikan siklus ini sebagai deadlock.

Keempat kondisi yang diperlukan terpenuhi: write lock akun bersifat mutually exclusive; kedua thread memegang satu lock sambil menunggu yang lain; lock tidak dapat diambil secara paksa dengan aman; dan penantian membentuk siklus. Saya tidak akan menghapus mutual exclusion karena ini melindungi saldo. Saya akan memutus circular wait dengan mendefinisikan satu total order untuk lock akun, mendeduplikasi ID, memperoleh lock dalam urutan naik, dan melepaskannya secara terbalik. Jika setiap alur hanya menunggu dari peringkat yang lebih rendah ke peringkat yang lebih tinggi, siklus akan mengharuskan peringkat meningkat dan kemudian kembali ke titik awal yang lebih rendah, yang mana hal itu mustahil.

Aturan ini harus mencakup transfer online, refund, pekerjaan batch, dan tool perbaikan. Critical section hanya berisi validasi dan mutasi state, bukan remote call. Timeout dapat melenyapkan penantian ini setelah pelepasan penuh, tetapi itu tidak membuktikan bahwa protokol penguncian bersifat asiklik. Timeout dan retry yang terjadi bersamaan dapat menjadi livelock, sehingga setiap jalur timeout memerlukan batas percobaan, randomized backoff, dan idempotency key.

Di lingkungan produksi, saya akan mengonstruksi graf penunggu-ke-pemilik dari thread dump atau data tunggu database, sambil memperhatikan cakupan masing-masing detektor. Jika PostgreSQL mendeteksi deadlock transaksi, ia akan menggugurkan satu transaksi. Saya akan melakukan rollback dan mencoba kembali seluruh transaksi dengan batas tertentu, tanpa berasumsi permintaan mana yang menjadi korban, dan memublikasikan pesan eksternal hanya melalui jalur post-commit yang idempoten.

Untuk verifikasi, sebuah barrier memungkinkan A mengunci 42 dan B mengunci 84 sebelum keduanya meminta lock kedua, mereproduksi implementasi lama secara andal. Versi yang terurut menerima input terbalik yang sama dan hanya akan menunjukkan penantian asiklik sebelum selesai. Saya juga akan menguji akun yang identik, operasi tiga akun, pembersihan exception, bypass job, dan rollback database sambil memeriksa total saldo, duplikasi efek samping, jumlah deadlock, dan kegagalan terminal."

Jawaban ini menghubungkan definisi, pembuktian, pilihan rekayasa, pemulihan, dan validasi. Jika pewawancara hanya menanyakan tentang empat kondisi, berhentilah setelah paragraf kedua. Lanjutkan ke perkakas (tooling) dan batasan retry ketika penanganan produksi menjadi pertanyaan lanjutan.

Kesalahan Umum

  • Menyatakan deadlock setiap kali sebuah thread terblokir → Pemegang lock yang lama mungkin masih membuat progres → Gambarkan edge penunggu-ke-pemilik dan konfirmasi adanya siklus di bawah model resource-instance yang tepat.
  • Hanya menghafal empat kondisi → Jawaban tidak memetakan ke kode maupun memilih solusi → Petakan setiap kondisi ke skenario dan sebutkan kondisi mana yang diputus oleh rancangan Anda.
  • Mengurutkan secara independen di dalam setiap fungsi → Modul mungkin berbeda pendapat mengenai kunci pengurutan atau peringkat jenis resource → Tentukan hierarki lock di seluruh repositori dan periksa setiap entry point.
  • Mengabaikan ID resource yang duplikat → Satu thread dapat memperoleh non-reentrant lock yang sama dua kali → Lakukan deduplikasi sebelum mengurutkan dan definisikan semantik transfer untuk akun yang sama.
  • Menganggap timeout sebagai desain yang asiklik → Urutan terbalik tetap ada, dan timeout dapat menggugurkan penantian yang sah → Lepaskan setiap lock yang dipegang dan tambahkan bounded backoff, idempotensi, serta terminal failure.
  • Melanjutkan di tengah jalan setelah deteksi siklus → State parsial bisa jadi basi dan efek samping dapat berulang → Rollback dan jalankan ulang transaksi secara lengkap dengan jalur post-commit yang idempoten.
  • Mengasumsikan setiap siklus graf resource membuktikan deadlock → Instance luar dapat melepaskan resource multi-instance → Pisahkan wait-for graph single-instance dari analisis alokasi multi-instance.
  • Mematikan pemilik lock secara paksa → Invariansi in-memory mungkin baru setengah terbarui → Ambil bukti dan restart hanya pada batasan yang state-nya dapat direkonstruksi.
  • Hanya menjalankan uji stres yang diacak → Kegagalan untuk mereproduksi tidak membuktikan ketiadaan urutan terbalik → Kunci interleaving dengan barrier, lalu tambahkan soak test untuk jalur yang tidak teridentifikasi.

Pertanyaan Lanjutan dan Tanggapan

Pertanyaan lanjutan 1: Apakah pengurutan tetap berfungsi ketika transfer mengunci tiga akun?

Ya, jika set lock yang lengkap dan terdeduplikasi diketahui sebelum perolehan dan diurutkan berdasarkan kunci stabil yang sama. Jika eksekusi menemukan akun secara dinamis, baca set kandidat tanpa lock, peroleh bersama-sama, dan validasi ulang versinya. Jika set tidak dapat diketahui, bagi transaksi atau gunakan deteksi di sekitar batasan yang mendukung rollback daripada memperolehnya secara inkremental dengan urutan lokal.

Pertanyaan lanjutan 2: Bagaimana cara Anda mengurutkan jenis resource yang berbeda?

Buat peringkat komposit, seperti customer sebelum account sebelum ledger shard, lalu ID yang stabil di dalam setiap jenis. Protokol penguncian bersama mengatur aturan ini, dan review serta pengujian memvalidasi edge lintas-jenis. Jika satu operasi harus masuk secara terbalik, rancang ulang arah panggilan atau lepaskan resource tingkat yang lebih rendah sebelum melintasi batasan daripada menambahkan pengecualian satu kali.

Pertanyaan lanjutan 3: Apakah tryLock dengan timeout 100 milidetik menyelesaikan deadlock?

Ini membatasi waktu tunggu percobaan ini ke jendela yang dikonfigurasi tetapi tidak membuktikan protokol asiklik. Seratus milidetik mungkin juga berada di bawah tail latency critical section yang sah dan menciptakan kegagalan palsu. Definisikan pelepasan lock yang telah diperoleh, rollback state parsial, bounded randomized backoff, idempotensi, dan terminal error; jika tidak, deadlock dapat berubah menjadi retry livelock.

Pertanyaan lanjutan 4: Mengapa meng-upgrade read lock menjadi write lock berbahaya?

Jika dua thread sama-sama memiliki shared read lock dan keduanya menunggu untuk di-upgrade menjadi exclusive write, masing-masing read lock memblokir upgrade pihak lain dan membentuk siklus. Utamakan protokol upgrade eksplisit yang disediakan oleh library. Tanpa itu, lepaskan read lock, bersaing untuk mendapatkan write lock, dan validasi ulang kondisinya karena state dapat berubah selama jeda tersebut.

Pertanyaan lanjutan 5: Jika PostgreSQL mendeteksi deadlock secara otomatis, apa yang tersisa untuk aplikasi?

Gunakan urutan multi-objek yang konsisten untuk mengurangi kemunculannya dan perlakukan error deadlock sebagai kegagalan seluruh transaksi. Baca ulang dan coba lagi dengan batasan tertentu, jadikan permintaan idempoten, dan catat retry serta terminal failure. Jangan berasumsi bahwa transaksi tertentu selalu kalah atau mengulangi tindakan eksternal yang tidak dapat dibatalkan setelah rollback.

Pertanyaan lanjutan 6: Apa perbedaan antara deadlock, livelock, dan starvation?

Partisipan yang mengalami deadlock tidak dapat membuat progres karena adanya siklus tunggu. Partisipan yang mengalami livelock mengeksekusi dan mengubah state tetapi berulang kali mengalah (yield) atau mencoba lagi tanpa pernah selesai. Starvation berarti salah satu partisipan ditolak untuk mendapatkan resource dalam waktu tanpa batas sementara yang lain dapat menyelesaikannya. Buktinya berbeda: siklus tunggu, perubahan state yang terus-menerus tanpa penyelesaian, dan penantian tidak adil yang berkepanjangan.

Sumber publik

Pertanyaan terkait