2013-07-03 28 views
0

我正在学习编写多线程代码。我理解Scala中同步运算符的字面含义。但是,当我运行下面的代码时,我不理解输出。难以理解同步定义

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; 
    } 
} 

同步放置和获取,该功能将永远持续下去,这是预期的。但是,当我删除同步的定义,输出将是

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

任何人都可以解释为什么结果看起来像这样?非常感谢。

+1

这种令人费解的行为是为什么我们现在有更好的(更认知易处理和更少错误 - 易于使用)编写并发和分布式系统的工具。我在谈论阿卡。如果你正在编写并发系统,那么你可以使用它。 –

回答

1

如果您不使用类似volatile或​​的东西,则JVM的内存型号不能保证为sequential consistency。这意味着每个线程基本上具有当前值n的独立视图。

我的猜测是,这样的事情正在发生:

  1. 第一个线程产卵
  2. 第一个线程运行put两次被卡住等待(?我猜N=2
  3. 第二个线程产卵,获取当前视图n=2
  4. 第二个线程运行两次get,使n降至0,并且等待卡住
  5. 由于没有同步结构在这里,每个线程保持的n价值的私人看法,而且也从未改变,他们只是停留停留在while循环

尝试使nvolatile看看会发生什么。 (我不会给你100%正确的行为,但我不认为它会卡住。)