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

在 put 和 get 中同步后,该函数将永远持续下去,这是意料之中的。但是,当我从定义中删除同步时,输出将是

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

谁能解释为什么结果看起来像这样?非常感谢。

4

1 回答 1

1

如果您不使用类似or的东西,JVM 的内存模型无法保证顺序一致性。这意味着每个线程本质上对 的当前值都有一个独立的视图。volatilesynchronizedn

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

  1. 第一个线程产生
  2. 第一个线程运行put两次并卡住等待(我猜N=2?)
  3. 第二个线程产生,获取当前视图n=2
  4. 第二个线程运行get两次,n降为 0,然后卡住等待
  5. 由于这里没有同步结构,每个线程都维护其对 的值的私有视图n,并且它永远不会改变——它们只是停留在while循环中

试着让n volatile看看会发生什么。(我不认为这会给你 100% 正确的行为,但我认为它也不会卡住。)

于 2013-07-03T15:17:36.643 回答