2013-03-02 2 views
12

나는 방해가되는 동작을 발견했습니다. for 루프에서 사용되는 범위는 하지 평행 일 때스칼라 : 개체 이니셜 라이저의 병렬 컬렉션으로 인해 프로그램이 중단됩니다.

object ParCollectionInInitializerTest { 
    def doSomething { println("Doing something") } 

    for (i <- (1 to 2).par) { 
    println("Inside loop: " + i) 
    doSomething 
    } 

    def main(args: Array[String]) { 
    } 
} 
이 프로그램은 완벽하게 무죄와

다음과 같은 출력이 제대로 실행 : 의 내가 단독 객체로 구성된 독립 프로그램이 있다고 가정 해 봅시다 :

루프 내부

: 1
이렇게 뭔가
루프 내부 : 2
뭔가

을하는 병렬 컬렉션 사용시

불행하게도, 프로그램은 이제까지 해봐요 메소드를 호출하지 않고 중단되므로 출력은 다음과 같다 : 루프 내

2
루프 내 1

그리고 프로그램이 중단됩니다.
이것은 그냥 심한 버그입니까? scala-2.10을 사용하고 있습니다.

+0

관련 : http : // stackoverflow.com/questions/27549671/java-static-initializers 진단 또는 교착 상태 교착 상태 – Rich

답변

15

이것은 구성이 완료되기 전에 싱글 톤 객체에 대한 참조를 해제 할 때 스칼라에서 발생할 수있는 고유 한 문제입니다. 객체가 완전히 생성되기 전에 다른 스레드가 객체 ParCollectionInInitializerTest에 액세스하려고하기 때문에 발생합니다. main 메서드와 아무 관련이 없습니다. main 메서드가 포함 된 개체를 초기화하는 것과 관련이 있습니다. REPL에서이 메서드를 실행하고 식 ParCollectionInInitializerTest을 입력하면 동일한 결과가 나타납니다. 또한 데몬 스레드 인 fork-join 작업자 스레드와 관련이 없습니다.

싱글 톤 객체는 지연 초기화됩니다. 모든 싱글 톤 객체는 한 번만 초기화 될 수 있습니다. 즉, 개체에 액세스하는 첫 번째 스레드 (경우에 따라 주 스레드)가 개체의 잠금을 가져 와서 초기화해야합니다. 이후에 오는 다른 모든 스레드는 주 스레드가 개체를 초기화하고 결국 잠금을 해제 할 때까지 기다려야합니다. 이것이 스칼라에서 싱글 톤 객체가 구현되는 방식입니다.

병렬 수집 작업자 스레드는 단일 스레드 개체에 액세스하여 doSomething을 호출하려고 시도하지만 주 스레드가 개체 초기화를 완료 할 때까지 기다릴 수 없습니다. 반면에, 메인 쓰레드는 병렬 작업이 완료 될 때까지 생성자를 기다린다. 이것은 모든 작업자 쓰레드가 완료 될 때 조건이된다. 메인 쓰레드는 항상 싱글 톤을위한 초기화 락을 가지고있다. 따라서 교착 상태가 발생합니다.

다음과 같이 당신은, 또는 단순한 스레드, 2.10에서 선물이 동작이 발생할 수 있습니다

:

scala> ParCollection 

과 REPL을 :

def execute(body: =>Unit) { 
    val t = new Thread() { 
    override def run() { 
     body 
    } 
    } 

    t.start() 
    t.join() 
} 

object ParCollection { 

    def doSomething() { println("Doing something") } 

    execute { 
    doSomething() 
    } 

} 

작성 후 REPL에이를 붙여 멈 춥니 다.

+2

우수 설명, 감사합니다! –

+1

동시 차단 실행과 지연 초기화는 잘 작동하지 않습니다. 이것은 스칼라 (그리고 자바, 그 문제에 대한)에서보다 일반적인 문제이다. 이 SIP를 참조하십시오 : http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html – axel22

+0

레토르트는 아니지만 개발자에게는 함정이라고 생각합니다. 매우 초기 답변과 의견에 감사드립니다. 나는 그 대답이 그 길에 나에게 명백하게 밝혀 졌다고 믿는다. – matanster