2013-07-03 1 views
0

멀티 스레딩에서 코드를 작성하는 법을 배우고 있습니다. 스칼라에서 synchronized 연산자의 문자 적 ​​의미를 이해합니다. 그러나 다음 코드를 실행하면 결과를 이해할 수 없습니다.동기화 된 정의를 이해하기가 어려움

package examples 
import scala.concurrent.ops._ 

object concurrent extends App { 

    class BoundedBuffer[A](N:Int) { 
     var in = 0; 
     var out = 0; 
     var n = 0; 

     def put(x:A) = synchronized { 
      while(n>=N) 
      wait() 
      in = (in + 1)/N; 
      n = n+1; 
      println("In put.") 
      if(n==1) 
      notifyAll() 
     } 

     def get = synchronized { 
      while(n==0) 
      wait() 
      out = (out + 1)%N; 
      n = n-1; 
      println("In get.") 
      if(n == N-1) 
      notifyAll() 
     } 
    } 

    val buf = new BoundedBuffer[Int](10) 
    spawn { 
     while(true) 
      buf.put(0); 
    } 
    spawn { 
     while(true) 
      buf.get; 
    } 
} 

은 put in 및 get과 동기화되어 예상대로 기능이 계속됩니다. 그러나 동기화에서 동기화를 제거하면 출력은

In put. 
In put. 
In get. 
In get. 

이 될 수 있습니다. 왜 결과가 이렇게 보이는지 설명 할 수 있습니까? 고마워.

+1

이런 종류의 수수께끼 같은 행동은 왜 우리가 지금 훨씬 더 훌륭하게 (다루기 쉽고 오류가 적은) 경향이있는) 동시 및 분산 시스템 작성 도구. 나는 아카에 대해서 이야기하고있다. 동시 시스템을 작성하는 경우,이를 사용하는 것이 좋습니다. –

답변

1

volatile 또는 synchronized과 같은 것을 사용하지 않으면 JVM의 메모리 모델이 sequential consistency을 보장하지 않습니다. 이것은 각 스레드가 근본적으로 현재 값인 n의 독립적 인 뷰를 가짐을 의미합니다.

내 생각 엔 이런 일이 일어나고 있다는 것입니다 :

  1. 첫 번째 스레드가
  2. 첫 번째 스레드가 두 번 put를 실행하고 (? 내가 N=2 추측)
  3. 두 번째 스레드 급부상 대기 걸리면 생성합니다, n=2
  4. 두 번째 스레드는 get을 두 번 실행하여 n을 0으로 낮추고 대기 상태로 붙잡 힙니다.
  5. 더 동기화 구조가 없기 때문에 여기에 각 스레드는 n의 가치는 개인보기를 유지, 그것은 결코 변하지 않습니다 - 그들은 단지

nvolatile을 시도하고 무슨 일을 참조 while 루프에 갇혀있어. (나는 당신에게 100 % 정확한 행동을 줄 것이다. 그러나 그것도 붙어 버릴 것이라고 생각하지 않는다.)