교착 상태를 만드는 가장 짧은 코드


11

교착 상태 를 만드는 가장 짧은 코드를 작성하십시오 . 코드 실행이 중단되어야 작동하지 않습니다.

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){}}
}

그것은 일 필요는 없습니다 코드가 교착 상태에 들어가는 것을 확신 단지, 거의 확실하게 (당신이 무한한 시간 동안 실행하면 교착 상태 것이다).


동일한 스레드에서 동일한 (재진입하지 않는) 잠금을 두 번 잠그려고하면 교착 상태로 간주됩니까? (미안 해요 샌드 박스에서이 질문을 몰랐)
존 드보르작에게

@JanDvorak 하나의 스레드가 얻을 수없는 것을 기다리고 있기 때문에 코드 실행이 중단되는 상황을 만듭니다 (다른 스레드가 잡고 있기 때문에 첫 번째 스레드의 내용을 기다리는 중)? 아니면 하나의 실입니까? 하나의 스레드로 그러한 상황을 만들 수 있다면 괜찮습니다. 교착 상태에 대한 Wikepedia 기사를 읽으십시오.
저스틴

2
Code execution must halt이해가 안 돼요 멈 추면 교착 상태는 어떻습니까? 그냥 멍청이처럼 스핀 락하는 것보다 무언가를 기다리고 있다는 것을 의미합니까?
Cruncher

@Cruncher 작동하지 않는 예제를 살펴보십시오. 루프가 계속 실행되므로 코드 실행이 중지되지 않습니다. 예, 나는 회전하기보다는 기다리는 것을 의미합니다.
저스틴

따라서 Dyalog APL에서 UI 스레드 자체를 기다리게 할 수 있다면 Javascript 답변을 얻을 희망이 있습니까? Javascript 6 "wait ()"... ermmm. 아니. 관련 : 스레드가 교착 상태 자체가 가능합니까?
Nathan Cooper

답변:


11

디아 로그 APL (10)

⎕TSYNC⎕TID

⎕TSYNC주어진 스레드가 끝날 때까지 스레드를 대기 ⎕TID시키고 현재 스레드를 제공합니다.

Dyalog APL은 교착 상태를 인식 할 수 있으므로 즉시

DEADLOCK

재미있는 점은 추가 스레드를 생성 할 필요조차 없으므로 UI ​​스레드 자체를 기다리게 만드는 것입니다.

이것이 부정 행위이고 실제로 새로운 스레드가 필요한 경우 27 자로 수행 할 수 있습니다.

{∇⎕TSYNC&{⎕TSYNC⎕TID+1}&0}0

F & xFvalue의 새 스레드에서 실행 되고 x스레드 ID를 반환합니다. 그래서:

  • {⎕TSYNC⎕TID+1}&0 ID가 자신의 ID보다 하나 높은 스레드와 동기화 할 스레드를 작성합니다.
  • ⎕TSYNC& 이전 스레드와 동기화 할 새 스레드를 작성하고 방금 작성된 스레드보다 하나 더 높은 ID를 얻습니다 (아무것도 스레드를 작성하지 않는다고 가정).
  • 무한 루프를 일으켜 교착 상태가 될 때까지 스레드를 계속 만듭니다.

첫 번째 스레드가 실행되기 전에 두 번째 스레드가 생성되는 즉시 교착 상태가 발생합니다.

9:DEADLOCK

⎕TSYNC 0'. withTID` is로 2 바이트를 저장하십시오 0.
Adám

8

이동, 42

package main
func main(){<-make(chan int)}

작동 방식을 제공하지 않아서 죄송합니다. 이것은 익명의 int 채널을 생성하고 읽습니다. 이것은 값이 채널로 전송 될 때까지 메인 스레드를 일시 중지합니다. 다른 스레드가 활성화되지 않아 교착 상태가 발생하지 않으므로 분명히 발생하지 않습니다.


2
어떻게 작동합니까?
저스틴

4

루비, 39 자

T=Thread;t=T.current;T.new{t.join}.join

Johannes Kuhn의 Java answer 에서 부끄럽게 도난당한 크로스 조인을 사용하는 아이디어 .

특정 환경에 맞게 코드를 조정하면 4 자 ( 35까지 ) 를 줄일 수 있습니다. JRuby의 콘솔 IRB는 단일 스레드입니다.

T=Thread;T.new{T.list[0].join}.join


이것은 내 이전 솔루션입니다.

뮤텍스에 스레드를 고정시키는 것은 쉽습니다.

m=Mutex.new;2.times{Thread.new{m.lock}}

그러나 이것은 두 번째 스레드가 기술적으로 첫 번째 스레드를 기다리지 않기 때문에 적절한 교착 상태가 아닙니다. "보류 및 대기"는 Wikipedia에 따르면 교착 상태에 필요한 조건입니다. 첫 번째 스레드는 기다리지 않고 두 번째 스레드는 아무것도 보유하지 않습니다.

루비, 97 95 자

m,n=Mutex.new,Mutex.new
2.times{o,p=(m,n=n,m)
Thread.new{loop{o.synchronize{p.synchronize{}}}}}

이것은 전형적인 교착 상태입니다. 두 개의 스레드가 두 개의 리소스를 놓고 경쟁하여 성공하면 다시 시도합니다. 일반적으로 그들은 내 컴퓨터에서 1 초 안에 붙어 있습니다.

그러나 무한히 많은 스레드 (둘 중 어느 것도 CPU를 무한 소비하고 일부는 교착 상태)가 있으면 괜찮습니다.

루비, 87 85 자

m,n=Mutex.new,Mutex.new
loop{o,p=(m,n=n,m)
Thread.new{o.synchronize{p.synchronize{}}}}

내 테스트에 따르면 스레드 수가 약 4700에 도달하면 실패합니다. 각 스레드가 실행될 기회가있을 때까지 실패하지 않기를 바랍니다 (따라서 교착 상태 또는 마무리 및 새 공간을 확보하기 위해 공간 확보). 내 테스트에 따르면 실패가 발생한 후에 스레드 수가 떨어지지 않아 테스트 중에 교착 상태가 발생했음을 의미합니다. 또한 IRB는 테스트 후 사망했습니다.


왜 추가 op변수 가 필요 합니까? 당신은 통과 할 수 없습니다 mn새로운 스레드 하시나요?
Johannes Kuhn

@JohannesKuhn mn글로벌 있습니다. 두 스레드 모두 동일한 순서로 볼 수 있습니다. op스레드 로컬 (루프 반복로 범위)이다. 사용 t[...]하면 아마도 비싸 질 것이므로 클로저를 통해보다 매개 변수를 스레드에 전달하는 더 좋은 방법을 볼 수 없습니다. 추가 매개 변수를 추가 new하면 코드를 두 문자 씩 길게 할 수 있습니다.
John Dvorak

@JohannesKuhn 나는 당신의 논리 중 일부를 빌린 것을 신경 쓰지 않기를 바랍니다
John Dvorak

상관 없어요 잘 했어.
Johannes Kuhn

우리가 우리가 메인 스레드에 있다고 가정하면, 이것을 32 문자로 줄일 수 있습니다T=Thread;T.new{T.main.join}.join
histocrat


4

Bash + GNU coreutils, 11 바이트

mkfifo x;<x

x현재 디렉토리에 스트레이 FIFO 를 작성합니다 (따라서 해당 이름의 파일이 필요하지 않음). FIFO는 일반 파일과 같은 방식으로 삭제할 수 있으므로 정리하기가 어렵지 않습니다.

FIFO에는 쓰기 측과 읽기 측이 있습니다. 다른 프로세스가 다른 프로세스를 열 때까지 한 블록을 열려고 시도하는 것은 의도적으로 동기화 프리미티브로 설계된 것 같습니다. 여기에 하나의 스레드 만 있다고 가정하면로 스레드를 열려고 <x하면 멈 춥니 다. (다른 프로세스에서 해당 FIFO에 쓰기를 통해 교착 상태를 해제 할 수 있습니다.)

이것은 두 개의 자원이 있고 두 개의 스레드가 각각 하나가 있고 다른 스레드가 필요한 경우와 다른 교착 상태입니다. 오히려이 경우 자원이없고 프로세스에 자원이 필요합니다. 다른 답변을 바탕으로, 나는 이것이 중요하다고 생각하지만 교착 상태 순수 주의자가 답변을 허용하지 않는 방법을 이해할 수 있습니다.

생각해 보면, 실제로 세 가지 교착 상태와 같은 상황을 생각할 수 있습니다.

  1. "전통적인"교착 상태 : 두 개의 스레드가 각각 잠금 해제를 기다리는 중이며 다른 스레드가 보유합니다.

  2. 단일 스레드가 잠금이 해제되기를 기다리고 있지만 잠금 자체를 보유하므로 잠금을 해제 할 수 없습니다.

  3. 단일 스레드가 동기화 프리미티브가 릴리스되기를 기다리고 있지만 동기화 프리미티브는 자연적으로 잠긴 상태에서 시작하여 외부에서 잠금 해제해야하며 그렇게하기 위해 프로그래밍 된 것은 없습니다.

이것은 유형 3의 교착 상태이며 다른 두 가지와 근본적으로 다릅니다. 이론적으로 문제의 동기화 기본을 잠금 해제하는 프로그램을 작성한 다음 실행할 수 있습니다. 말했다 즉, 같은 많은 언어 당신이 아니에요 (당신이 소유하지 않은 잠금을 해제 할 수 있도록 주어진 입력 1과 2의 교착 상태에 적용 하는데 에 당신이 할 이유가 있다면 그렇게 할 이유가 없을 것 처음에는 자물쇠를 사용하지만 작동합니다 ...). 또한 다음과 같은 프로그램을 고려해 볼 가치가 있습니다.mkfifo x;<x;echo test>x; 이 프로그램은 유형 2 교착 상태와 반대입니다 (FIFO의 양쪽 끝을 열려고하지만 다른 쪽 끝을 열 때까지 한쪽 끝을 열 수는 없지만). 이 코드 이후에는 절대로 실행되지 않는 코드! 문제는 자물쇠가 교착 상태인지 여부는 자물쇠 사용의 의도에 달려 있기 때문에 객관적으로 정의하기가 어렵습니다 (특히 자물쇠의 유일한 목적은 교착 상태를 의도적으로 교착 상태로 만드는 것입니다) ).



2

glibc를 사용한 배쉬, 6 바이트

오래된 실을 되살려 서 죄송하지만 저항 할 수 없었습니다.

루트로 :

pldd 1

에서 남자 pldd :

버그
glibc 2.19부터 pldd가 깨졌습니다. 실행시 멈 춥니 다. 그것이 고쳐질 지 확실하지 않다.


원본이 시간에 민감하지 않은 한 오래된 트레드에 응답하는 데 아무런 문제가 없습니다.
Ad Hoc Garf Hunter

2

자바, 191

class B extends Thread{public static void main(String[]a)throws Exception{new B().join();}Thread d;B(){d=Thread.currentThread();start();}public void run(){try{d.join();}catch(Exception e){}}}

언 골프 드 :

class B extends Thread {
    Thread d;
    public static void main(String[] args) throws Exception {
        new B().join();
    }
    B() { // constructor
        d = Thread.currentThread();
        start();
    }
    public void run() {
        try {
            d.join();
        } catch (Exception e) {
        }
    }
}

새 스레드를 시작하고 join그 스레드에서이 스레드가 완료 될 때까지 기다립니다. 새 스레드는 원래 스레드와 동일합니다.


Error대신 던지고 잡는 것으로 짧게 만들 수 있습니까 Exception?
mbomb007

아니. Thread.join()를 throw InteruptedException의 서브 클래스가 아닌 인 Error.
Johannes Kuhn

2

Tcl, 76

package r Thread;thread::send [thread::create] "thread::send [thread::id] a"

이중 자물쇠.

그러면 새 스레드가 생성되고 다른 스레드가 스레드에게 메시지 (스크립트 실행)를 보내도록 지시합니다.

그러나 다른 스레드에 메시지를 보내는 것은 일반적으로 스크립트가 실행될 때까지 차단됩니다. 그리고 차단하는 동안 메시지가 처리되지 않으므로 두 스레드가 다른 스레드가 메시지를 처리하기를 기다립니다.


어떻게 작동합니까?
John Dvorak

thread::send다른 스레드에서 실행되어야하는 스크립트를 큐에 넣고 완료 ​​될 때까지 기다립니다. 그래서 결국에 우리는 스레드 2 일 개 대기 스레드와 스레드 1. 2 대기 스레드가
요하네스 쿤

1

모니터 남용이있는 대체 Java (248 자)

class A{public static void main(String args[]) throws Exception{final String a="",b="";new Thread(new Runnable(){public void run(){try {synchronized(b){b.wait();}} catch (Exception e) {}a.notify();}}).start();synchronized(a){a.wait();}b.notify();}}

1

스칼라, 104 바이트

class A{s=>lazy val x={val t=new Thread{override def run{s.synchronized{}}};t.start;t.join;1}};new A().x

게으른 값 초기화 블록은 조건이 충족 될 때까지 일시 중단됩니다. 이 조건은 lazy val x의 값을 읽어야 만 충족 될 수 있습니다.이 조건을 완료해야하는 다른 스레드는이를 수행 할 수 없습니다. 따라서, 순환 의존성이 형성되고 지연 지연은 초기화 될 수 없다.


어떻게 작동합니까?
애디슨 크럼

설명을 추가했습니다.
Martin Seeler

1

코 틀린, 35/37/55 바이트

일반적인 주제 : Thread.currentThread().join().

이 제출에 대한 JVM 버그 / 매우 특수한 코드를 제외하면 현재 실행 스레드가 비활성화되어 자체 죽기를 기다리는 동안이 shoud는 반환되지 않습니다.


이블 속성 : 35 바이트 (비경쟁) : 35 바이트

val a=Thread.currentThread().join()

이것을 속성 선언이 유효한 곳에두면 초기화하는 사람이 교착 상태에 빠집니다. 최상위 레벨 특성의 경우 해당 파일에 대해 맵핑 된 JVM 클래스를 초기화하는 클래스 로더 (기본값 [file name]Kt.class)입니다.

"어디서나 최상위 속성으로 사용"하는 것은 제한적이기 때문에 비경쟁입니다.


기능 : 37 바이트

fun a()=Thread.currentThread().join()


main () : 55 바이트

fun main(a:Array<String>)=Thread.currentThread().join()


1

PowerShell, 36 28 23 바이트

gps|%{$_.waitforexit()}

자기 교착 상태. 우리는 모든 프로세스를 가져 와서 Get-Process각 프로세스가 종료 될 때까지 참을성있게 기다립니다 ... 프로세스가 자체적으로 대기하기 때문에 거의 절대 발생하지 않습니다.

편집-Roman Gräf 덕분에 5 바이트 절약


(gps)|%{$_.waitforexit()}3 바이트가 짧고 모든 프로세스가 종료 될 때까지 기다립니다.
Roman Gräf

@ RomanGräf 실제로, gps그 경우에는 주변의 괄호가 필요하지 않으므로 총 5 바이트를 절약했습니다.
AdmBorkBork

0

C (Linux 만 해당), 31 바이트- 온라인으로 사용해보십시오!

main(a){syscall(240,&a,0,a,0);}

시스템 호출 240 (0xf0)은 futex (2) 또는 빠른 사용자 공간 뮤텍스입니다. 문서에는 첫 번째 인수가 futex에 대한 포인터이고 두 번째 인수는 연산입니다 (0은 FUTEX_WAIT를 의미합니다. 즉, 다른 스레드가 futex를 잠금 해제 할 때까지 기다립니다). 세 번째 인수는 여전히 futex가 잠겨있는 동안 예상되는 값이고, 네 번째는 시간 초과에 대한 포인터입니다 (시간 초과가 없으면 NULL).

분명히, futex를 잠금 해제 할 다른 스레드가 없기 때문에 자체 교착 상태에서 영원히 대기합니다. top교착 상태 스레드에서 예상되는 것처럼 프로세스가 CPU 시간을 사용하지 않는지 ( 또는 다른 작업 관리자 를 통해) 확인할 수 있습니다 .


0

Julia 0.6 , 13 바이트

질문보다 새로운 언어. 실행 예정이 아닌 작업 (예 : go-routine)은 현재 동일한 스레드에 있으며, 이후 버전의 Julia에서는 다른 스레드에있을 수 있습니다.

wait(@task +)

온라인으로 사용해보십시오!


0

BotEngine, 3x3 = 9 (9 바이트)

v
lCv
> <

5 단계는 서로의 이동을 무기한 대기하는 두 봇으로 끝납니다. 한 봇은 다른 봇이 오른쪽 하단 광장 밖으로 이동할 때까지 대기하기 때문에 움직일 수 없으며 다른 봇은 대기하기 때문에 움직일 수 없습니다. 첫 번째 봇이 하단 중앙 광장 밖으로 이동합니다.


0

폭포 모델 (비율), 13 바이트

[[2,1],[1,1]]

온라인으로 사용해보십시오!

재미있는 답변이 있습니다. 이것은 Waterfall 모델에서 가능한 가장 간단한 무한 루프입니다. Waterfall 모델의 변수는 다른 상황이 발생하지 않을 때마다 반복적으로 감소합니다.이 프로그램은 감소 할 때마다 증가하는 변수를 정의하므로 아무 일도 일어날 수 없습니다.

이 질문은 무한 루프가 아닌 교착 상태를 요구합니다. 그러나 특정 구현의 동작을 활용할 수 있습니다. 최적화 수준 2 이상 (기본값은 3)에서 인터프리터 Ratiofall은 무한 루프를 감지하여이를 교착 상태로 최적화합니다! 적어도 언어의 구현 (일반적으로이 사이트의 경우)에 의해 정의 된 언어를 고려한다면,이 프로그램은 무한 루프가 아닌 교착 상태를 정의합니다.

온라인 사용해보십시오!의 시간 보고서에서 교착 상태에 대한 증거를 볼 수 있습니다. 위의 링크 :

Real time: 60.004 s
User time: 0.006 s
Sys. time: 0.003 s
CPU share: 0.01 %
Exit code: 124

프로그램은 60 초 동안 실행되었지만 (TIO가 자동으로 종료 할 때까지), 대부분의 시간 동안 CPU 사용, 프로그램 실행에 소요 된 시간, 프로그램 대신 커널이 소비 한 시간이 없었습니다.

더 강력한 증거를 얻으려면 다음과 같은 시스템 호출 수준 디버거에서 Ratiofall을 실행할 수 있습니다 strace. Linux에서이 작업 futex을 수행하면 잠금이 해제되지 않는 시스템 호출 에서 인터프리터 차단이 표시 됩니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.