Tulis kode terpendek untuk membuat jalan buntu . Eksekusi kode harus dihentikan, jadi ini tidak berfungsi:
public class DeadlockFail extends Thread{ //Java code
public static void main(String[]a){
Thread t = new DeadlockFail();
t.start();
t.join();
}
//this part is an infinite loop; continues running the loop.
public void run(){while(true){}}
}
Tidak perlu memastikan bahwa kode mengalami kebuntuan , hanya hampir pasti (jika Anda menjalankan untuk waktu yang tak terbatas, itu akan menemui jalan buntu).
code-golf
concurrency
Justin
sumber
sumber
Code execution must halt
Saya tidak mengerti. Bagaimana itu jalan buntu jika berhenti? Apakah maksud Anda itu akan menunggu sesuatu daripada hanya berputar seperti bajingan?Jawaban:
Dyalog APL (10)
⎕TSYNC
membuat utas menunggu sampai utas yang diberikan berakhir,⎕TID
memberikan utas saat ini.Dyalog APL dapat mengenali kebuntuan, sehingga segera merespons
Yang menyenangkan adalah, Anda bahkan tidak perlu menelurkan utas tambahan, membuat utas UI menunggu sendiri.
Jika ini curang dan utas baru benar-benar diperlukan, Anda bisa melakukannya dalam 27 karakter:
F & x
berjalanF
di utas baru pada nilaix
, dan mengembalikan ID utas. Begitu:{⎕TSYNC⎕TID+1}&0
membuat utas yang akan disinkronkan dengan utas yang ID-nya lebih tinggi daripada miliknya,⎕TSYNC&
membuat utas baru yang akan disinkronkan dengan utas sebelumnya, dan yang mendapat ID yang lebih tinggi dari utas yang baru saja dibuat (dengan asumsi tidak ada yang lain yang membuat utas).∇
menyebabkan loop tak terbatas (jadi kami terus membuat utas hingga ada jalan buntu).Ini akan menemui jalan buntu segera setelah utas kedua dibuat sebelum yang pertama mulai berjalan, yang segera:
sumber
⎕TSYNC 0'.
⎕TID` adalah0
.Pergi, 42
Permintaan maaf, downvoter, karena tidak memberikan cara kerjanya. Ini menciptakan saluran int anonim dan membaca darinya. Ini menjeda utas utama hingga nilai dikirim ke saluran, yang jelas tidak pernah terjadi karena tidak ada utas lain yang aktif, dan karenanya, jalan buntu.
sumber
Ruby, 39 karakter
Gagasan untuk menggunakan cross-join tanpa malu-malu dicuri dari jawaban Java Johannes Kuhn .
Kita dapat mengurangi empat karakter (mencapai 35 ) jika kita menyelaraskan kode ke lingkungan tertentu. Konsol JRuby, IRB, adalah single-threaded:
Ini solusi saya sebelumnya:
mendapatkan utas macet di mutex itu mudah:
tapi ini bukan jalan buntu, karena utas kedua secara teknis tidak menunggu utas pertama. "tahan dan tunggu" adalah kondisi yang diperlukan untuk kebuntuan menurut Wikipedia. Utas pertama tidak menunggu, dan utas kedua tidak menahan apa pun.
Rubi,
9795 karakterini adalah kebuntuan klasik. Dua utas bersaing untuk dua sumber daya, mencoba lagi jika mereka berhasil. Biasanya mereka macet dalam sedetik di mesin saya.
Tetapi, jika memiliki banyak utas (tidak ada yang mengkonsumsi CPU secara tak terbatas dan beberapa di antaranya kebuntuan) tidak apa-apa,
Rubi,
8785 karakterMenurut pengujian saya, itu gagal setelah jumlah utas mencapai sekitar 4700. Semoga tidak gagal sampai setiap utas memiliki kesempatan untuk berjalan (sehingga deadlock atau finishing dan membebaskan ruang untuk yang baru). Menurut pengujian saya, jumlah utas tidak turun setelah kegagalan terjadi, artinya kebuntuan memang terjadi selama pengujian. Juga, IRB meninggal setelah tes.
sumber
o
&p
variabel? Tidak bisakah kamu lulusm
dann
untuk Thread baru?m
dann
bersifat global. Kedua utas melihatnya dalam urutan yang sama.o
danp
bersifat thread-local (mencakup untuk iterasi loop). Menggunakant[...]
mungkin akan menjadi mahal, dan saya tidak bisa melihat cara yang lebih baik untuk melewatkan parameter ke thread daripada melalui penutupan. Menambahkan parameter ekstra untuknew
memperpanjang kode dengan dua karakter.T=Thread;T.new{T.main.join}.join
Python, 46
(self-deadlock)
sumber
from threading import* Semaphore(0).acquire()
lebih pendek dengan satu byte saya pikirBash + GNU coreutils, 11 byte
Membuat FIFO yang tersesat
x
di direktori saat ini (jadi Anda tidak perlu memiliki file dengan nama itu). FIFO dapat dihapus dengan cara yang sama seperti file biasa, jadi tidak sulit untuk dihapus.FIFO memiliki sisi penulisan dan sisi baca; mencoba untuk membuka satu blok sampai proses lain membuka yang lain, dan ini tampaknya sengaja dirancang sebagai sinkronisasi primitif. Karena hanya ada satu utas di sini, segera setelah kami mencoba membukanya
<x
, kami macet. (Anda dapat menghilangkan kebuntuan melalui menulis ke FIFO yang bersangkutan dari proses lain.)Ini adalah jenis kebuntuan yang berbeda dari satu ketika ada dua sumber daya, dan dua utas masing-masing memiliki satu dan membutuhkan yang lain; alih-alih, dalam hal ini, tidak ada sumber daya dan proses membutuhkannya. Berdasarkan jawaban yang lain, saya pikir ini penting, tetapi saya bisa mengerti bagaimana seorang purist yang buntu ingin melarang jawaban.
Kalau dipikir-pikir, saya benar-benar bisa memikirkan tiga situasi seperti kebuntuan:
Kebuntuan "tradisional": dua utas masing-masing menunggu kunci untuk dilepaskan, yang dipegang oleh utas lainnya.
Satu utas sedang menunggu kunci untuk dilepaskan, tetapi itu menahan kunci itu sendiri (dan dengan demikian menghalangi dirinya untuk dapat melepaskannya).
Utas tunggal sedang menunggu sinkronisasi primitif dirilis, tetapi primitif sinkronisasi dimulai dalam keadaan terkunci secara alami dan harus dibuka kuncinya secara eksternal, dan tidak ada yang diprogram untuk melakukan itu.
Ini adalah jalan buntu dari tipe 3, yang secara fundamental berbeda dari dua lainnya: Anda bisa, secara teori, menulis sebuah program untuk membuka kunci primitif sinkronisasi yang dimaksud, lalu menjalankannya. Yang mengatakan, hal yang sama berlaku untuk deadlock dari tipe 1 dan 2, mengingat bahwa banyak bahasa memungkinkan Anda untuk melepaskan kunci yang tidak Anda miliki (Anda tidak seharusnya dan tidak memiliki alasan untuk melakukannya jika Anda memiliki alasan untuk gunakan kunci di tempat pertama, tetapi berhasil ...). Juga, ada baiknya mempertimbangkan program seperti
mkfifo x;<x;echo test>x
; semacam program yang kebalikan dari kebuntuan tipe 2 (itu mencoba untuk membuka kedua ujung FIFO, tetapi tidak dapat membuka satu ujung sampai setelah membuka ujung lainnya), tetapi itu dibuat dari yang ini melalui penambahan tambahan kode yang tidak pernah berjalan setelah ini! Saya kira masalahnya adalah apakah kunci macet atau tidak tergantung pada niat di balik penggunaan kunci, sehingga sulit untuk mendefinisikan secara obyektif (terutama dalam kasus seperti ini di mana satu-satunya tujuan kunci adalah untuk menghasilkan kebuntuan dengan sengaja ).sumber
C #, 100
Lihat: Kebuntuan tanpa kunci
sumber
static C
keMain
?Bash dengan glibc, 6 Bytes
Maaf untuk menghidupkan kembali utas lama, tetapi tidak bisa menolak.
Sebagai root:
Dari man pldd :
sumber
Jawa, 191
Tidak Disatukan:
Mulai Thread baru dan
join
di atasnya (tunggu sampai utas ini selesai), sedangkan utas baru melakukan hal yang sama dengan Utas asli.sumber
Error
bukanException
?Thread.join()
melemparInteruptedException
, yang bukan merupakan subclass dariError
.Tcl, 76
Jalan buntu.
Ini menciptakan Utas baru, dan memberi tahu utas lainnya untuk mengirim pesan kepada saya utas (skrip untuk dijalankan).
Tetapi mengirim pesan ke Thread lain biasanya memblokir sampai skrip dieksekusi. Dan ketika sedang memblokir, tidak ada pesan yang diproses, jadi kedua Thread menunggu yang lain untuk memproses pesan mereka.
sumber
thread::send
mengantri skrip yang harus dieksekusi di utas lain dan menunggu sampai selesai Jadi pada akhirnya kita memiliki Thread 1 menunggu Thread 2, dan Thread 2 menunggu Thread 1.java alternatif dengan penyalahgunaan monitor (248 karakter)
sumber
Scala, 104 byte
Blok inisialisasi lazy ditangguhkan sampai suatu kondisi terpenuhi. Kondisi ini hanya dapat dipenuhi dengan membaca nilai lazy val x - utas lain yang seharusnya menyelesaikan kondisi ini tidak dapat melakukannya. Dengan demikian, ketergantungan melingkar terbentuk, dan val malas tidak dapat diinisialisasi.
sumber
Kotlin, 35/37/55 byte
Tema umum:
Thread.currentThread().join()
.Tidak termasuk bug JVM / kode yang sangat terspesialisasi terhadap pengajuan ini, shoud ini tidak akan pernah kembali karena utas eksekusi saat ini dinonaktifkan dan menunggu sendiri untuk mati.
Properti jahat: 35 byte (tidak bersaing): 35 byte
val a=Thread.currentThread().join()
Menempatkan ini di mana saja pernyataan properti valid akan menemui jalan buntu siapa pun yang menginisialisasi itu. Dalam kasus properti tingkat atas, itu akan menjadi classloader menginisialisasi kelas JVM yang dipetakan untuk file itu (secara default
[file name]Kt.class
).Non-bersaing karena "menempatkan ini sebagai properti tingkat atas di mana saja" adalah membatasi.
Fungsi: 37 byte
fun a()=Thread.currentThread().join()
main (): 55 byte
fun main(a:Array<String>)=Thread.currentThread().join()
sumber
PowerShell,
362823 byteKebuntuan diri. Kami mendapatkan semua proses dengan
Get-Process
dan kemudian menunggu dengan sabar untuk masing-masing keluar ... yang akan terjadi kira-kira tidak pernah, karena proses akan menunggu dengan sendirinya.Sunting - Disimpan 5 byte berkat Roman Gräf
sumber
(gps)|%{$_.waitforexit()}
lebih pendek tiga byte dan menunggu semua proses untuk keluar.gps
di sekitar dalam kasus itu, jadi total 5 byte disimpan.C (hanya Linux), 31 Bytes - Cobalah online!
System call 240 (0xf0) adalah futex (2) , atau mutasi userspace cepat. Dokumentasi menyatakan bahwa argumen pertama adalah pointer ke futex, argumen kedua adalah operasi (0 berarti FUTEX_WAIT, yaitu, tunggu sampai utas lain membuka futex). Argumen ketiga adalah nilai yang Anda harapkan dimiliki futex saat masih terkunci, dan argumen keempat adalah pointer ke batas waktu (NULL tanpa batas waktu).
Jelas, karena tidak ada utas lain untuk membuka kunci, itu akan menunggu selamanya di jalan buntu yang ditimbulkan sendiri. Dapat diverifikasi (melalui
top
atau task manager lainnya) bahwa proses tidak menggunakan waktu CPU, seperti yang kita harapkan dari utas kebuntuan.sumber
Julia 0,6 , 13 byte
Bahasa lebih baru dari pertanyaan. Tunggu tugas (seperti rutinitas, saat ini berada di utas yang sama, di versi mendatang Julia mungkin ada di utas lain) yang tidak dijadwalkan untuk berjalan.
Cobalah online!
sumber
BotEngine, 3x3 = 9 (9 byte)
Langkah 5 diakhiri dengan dua bot yang menunggu tanpa batas satu sama lain untuk bergerak ... satu bot tidak dapat bergerak karena menunggu bot lain bergerak keluar dari kotak kanan bawah, dan bot lainnya tidak dapat bergerak karena menunggu bot pertama untuk keluar dari alun-alun tengah bawah.
sumber
The Waterfall Model (Ratiofall), 13 byte
Cobalah online!
Inilah jawaban yang menyenangkan. Ini adalah loop tak terhingga yang paling sederhana dalam The Waterfall Model (variabel dalam The Waterfall Model berulang kali berkurang setiap kali tidak ada yang lain; program ini mendefinisikan variabel yang menambah sendiri setiap kali menurun, sehingga tidak ada cara apa pun yang bisa terjadi).
Pertanyaannya meminta jalan buntu, bukan loop tak terbatas. Namun, kita dapat mengeksploitasi perilaku implementasi spesifik. Pada tingkat pengoptimalan 2 atau lebih tinggi (standarnya adalah 3), penerjemah Ratiofall akan mendeteksi infinite loop, dan mengoptimalkannya ... ke jalan buntu! Jadi setidaknya jika kita menganggap bahasa didefinisikan oleh implementasi mereka (yang biasanya terjadi di situs ini), program ini memang mendefinisikan kebuntuan, bukan loop tak terbatas.
Anda dapat melihat bukti kebuntuan dari laporan waktu di Try it Online! tautan di atas:
Program berjalan selama 60 detik (sampai TIO secara otomatis menghentikannya), tetapi untuk sebagian besar waktu itu, tidak ada penggunaan CPU, tidak ada waktu yang dihabiskan oleh program yang berjalan, dan tidak ada waktu yang dihabiskan oleh kernel atas nama program.
Untuk mendapatkan bukti yang lebih kuat, Anda dapat menjalankan Ratiofall di bawah debugger tingkat sistem panggilan seperti
strace
; melakukan ini di Linux akan menunjukkan pemblokiran interpreter padafutex
panggilan sistem yang mencoba mengambil kunci yang tidak akan pernah dirilis.sumber
Perl 6 , 24 byte
Cobalah online!
Buat semafor dengan nol izin dan kemudian coba untuk mendapatkannya.
sumber