8

使用play,我的控制器调用Foo服务,一个对象。这个使用val's 和immutable data structuresonly 的对象将被多个客户端调用。

当我的Controller调用Foo.doQuery()多个线程时,会发生什么?

如果客户端 1 调用执行Foo.doQuery(),客户端 2 的调用是否Foo.doQuery()必须等待?

我很好奇我是否应该简单地为每个实例创建一个新类Foo,但我想知道val在多线程环境中仅使用 Scala 单例会发生什么。

4

2 回答 2

12

不,Scala 对象并不意味着锁(java 中的“同步”),因此客户端 2 不必等待。如果您没有显式向代码添加锁,则客户端 1、客户端 2 和客户端 n 都可以同时运行。

考虑到

object MyObject { ... }

作为

class MyClass(..) { ... }
lazy val MyObject = new MyClass(..)

可以使用“同步”功能应用锁,如下所示:

def doQuery = synchronized {
  ..
  ..
}

== 编辑 ==

至于评论中的问题,线程(或调用)堆栈和变量共享与使用不可变引用和/或不可变数据结构的控制器无关。重要的是你在哪里定义你的变量。如果您在方法(方法变量)中定义了一个变量,无论是 val 还是 var,那么每次调用该方法时,都会为调用线程创建该变量。另一方面,如果您在类或对象级别(实例变量)定义变量,则对实例方法的所有调用始终共享同一个实例变量。

在您的情况下,我认为您可以将控制器实现为单例对象,因为不可变引用和数据结构很好......不可变。它们是否共享并不重要。

于 2013-11-12T16:55:12.680 回答
0

为了说明@harp seal pup 的答案,这里有一个带有输出的示例演示,
我们可以观察到可变变量myname受到每个正在运行的线程的影响。
但是val thname对于每个线程,不可变对象不会受到影响或锁定。

object ObjectMultiThreadingTest {

  def main(args: Array[String]): Unit = {

    for (x <- 1 to 5) {
      var thread = new MyThread()
      thread.setName("Thread number :" + x.toString)
      thread.start()
    }
  }

  class MyThread extends Thread {
    override def run(): Unit = {
      Singleton.myname = this.getName
      Singleton.call(this.getName)
    }
  }

  object Singleton {
    var myname = "Singleton"
    def call(threadName: String): Unit = {
      val thName = threadName
      val random = new Random
      for (i <- 1 to 5) {
        println("My Name is set by " + myname)
        val sleeptime = random.nextInt(1000)
        println(
          "But, I am now running " + thName + ", sleeping for " + sleeptime
        )
        Thread.sleep(sleeptime)
      }
    }

  }
}

输出:

My Name is set by Thread number :5
My Name is set by Thread number :5
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 498
My Name is set by Thread number :5
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 968
But, I am now running Thread number :4, sleeping for 232
But, I am now running Thread number :2, sleeping for 562
But, I am now running Thread number :1, sleeping for 204
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 315
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 100
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 749
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 66
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 4
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 332
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 899
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 679
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 849
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 157
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 694
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 864
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 591
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 702
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 339
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 959
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 443
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 522
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 368
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 851
于 2020-03-29T15:49:07.113 回答