2017-05-17 1 views
2

실용 신안입니다. 다음과 같이 두 클래스 A와 B를 만들었습니다.Java에서 스택 오버플로 예외가 발생했습니다.

public class A { 

    private B b; 

    public void setB(B b) { 
     this.b = b; 
    } 

    synchronized void foo() { 
     b.foo(); 
     System.out.println("Hi A"); 
    } 
} 

public class B { 

    private A a; 

    public void setA(A a) { 
     this.a = a; 
    } 

    synchronized void foo() { 
     a.foo(); 
     System.out.println("Hi B"); 
    } 
} 

이제 Runnable 인터페이스를 구현하는 두 개의 다른 클래스를 만들었습니다.

public class AThread implements Runnable{ 
    private A a; 
    public AThread(A a){ 
     this.a = a; 
    } 
    @Override 
    public void run() { 
     a.foo(); 
    } 

} 

public class BThread implements Runnable { 
    private B b; 
    public BThread(B a){ 
     this.b = b; 
    } 
    @Override 
    public void run() { 
     b.foo(); 
    } 

} 

주요 방법에서, 나는이

public static void main(String args[]) { 
     A a = new A(); 
     B b = new B(); 
     a.setB(b); 
     b.setA(a); 
     Runnable r1 = new AThread(a); 
     Runnable r2 = new BThread(b); 
     Thread t1 = new Thread(r1); 
     t1.start(); 

    } 

이 코드를 실행하고 코드 -, 나는 다음과 같은 예외를 가지고 다음 작성했습니다.

Exception in thread "Thread-0" java.lang.StackOverflowError 
    at student.B.foo(B.java:21) 
    at student.A.foo(A.java:21).. 

경로의 원인이 무엇인지 설명하고 해결할 수 있습니까?

+4

개체의'foo()'메서드를 호출하면 무한 재귀 호출 시퀀스가 ​​발생합니다. –

답변

11

무엇을 기대하셨습니까?

당신은 A에서 foo() 방법은 스택 오버플로 될 때까지, 등등 Afoo() 방법이라고 B에서 foo() 메소드를 호출하고 있습니다.

원형 메서드 호출을 피함으로써이를 해결할 수 있습니다.

+0

어떤 사람이 나에게이 문제를 주었고 어떻게하면 쓰레드를 안전하게 만들 수 있는지 말해 주었다. –

+0

이것은 까다로운 질문입니까? 나는 새로운 스레드입니다. 나는 그것이 DeadLock 상황이라고 생각했다. –

+1

@SubhabrataMondal 교착 상태가 아닙니다. 그것은 Eran이 언급 한 것처럼 순환 호출입니다. 다른 질문이있는 경우 새 게시물에서 질문해야합니다. – bradimus

1

함수를 호출하면 스택은 호출 된 함수의 주소를 저장하고 함수가 완료되면 제거합니다. A.foo에서는 B.foo를 호출하고 B.foo에서는 A.foo를 호출합니다. 그래서 스택은 Bfoo와 A.foo의 주소로 채워집니다. 루프는 끝나지 않지만 스택의 크기는 끝납니다. 그래서 나는 무한 루프를 없애기 위해 노력할 것을 제안한다. 내가 전문가가 아니기 때문에 너 한테 어떻게 말할 수 없어.

0

다른 사람들이 이미 언급했듯이 StackOverflowError은 스레드와 아무 관련이 없습니다. 아마도 단순화 된 예가이를 명확하게 할 수 있습니다. 그것은 어떤 Thread의를 포함하지 않는 다음 코드를 사용하여 재현 할 수

: ... 결국 스택 오버 플로우로 연결되는 A.foo 호출

public static void main(String args[]) { 
    A a = new A(); 
    B b = new B(); 
    a.setB(b); 
    b.setA(a); 
    a.foo(); 
} 

A.foo 전화 B.foo. 예 : t1에 여기에 주 스레드 인 Thread이 하나만 있습니다. Runnable r2을 전혀 실행하지 않습니다.

the comments on another question에서 의심을 해결하기 위해 : 여러 스레드가 동일한 잠금을 획득하려고하면 교착 상태는 발생할 수 있습니다, 그것은 예외로 이어질하지 않을
- 일반적으로 교착 상태의 효과는 아무것도 전혀 발생하지 않는다는 것이다 잠긴 스레드는 절대로 종료되지 않습니다.

관련 문제