gpt4 book ai didi

multithreading - 玩 Scala 和线程安全

转载 作者:行者123 更新时间:2023-12-04 06:40:07 26 4
gpt4 key购买 nike

该项目是使用 Play framework 编写的和 Scala语言。
我已经实现了compile time dependency .
我从 Play 中遵循了这个例子:

https://github.com/playframework/play-scala-compile-di-example

看着MyApplicationLoader.scala :

import play.api._
import play.api.routing.Router

class MyApplicationLoader extends ApplicationLoader {
private var components: MyComponents = _

def load(context: ApplicationLoader.Context): Application = {
components = new MyComponents(context)
components.application
}
}

class MyComponents(context: ApplicationLoader.Context)
extends BuiltInComponentsFromContext(context)
with play.filters.HttpFiltersComponents
with _root_.controllers.AssetsComponents {

lazy val homeController = new _root_.controllers.HomeController(controllerComponents)

lazy val router: Router = new _root_.router.Routes(httpErrorHandler, homeController, assets)
}

和以下代码行:
 lazy val homeController = new _root_.controllers.HomeController(controllerComponents)

我的理解是 HomeController 只有一个实例首次创建 HomeController叫做。
只要应用程序存在,该实例就会存在。这些说法正确吗?
HomeController在我的应用程序中看起来像这样:
class HomeController{

val request = // some code here

val workflowExecutionResult = Workflow.execute(request)

}

所以 Workflowobject 类型而不是 class .
Workflow看起来像这样:
object Workflow {
def execute(request: Request) = {

val retrieveCustomersResult = RetrieveCustomers.retrieve()
// some code here

val createRequestResult = CreateRequest.create(request)
// some code here

workflowExecutionResult
}
}

所以 Workflow调用几个域服务,每个域服务的类型为 object而不是 class .
域服务中的所有值都是不可变的,我使用的是 val无处不在。

这足以确保线程安全吗?

我在问,因为我习惯写 C# Web APIs在哪里 HomeController看起来像这样:
class HomeControllerInSeeSharpProject{

// some code here

var request = new Request() // more code here
var workflow = new WorkflowInSeeSharpProject()
var workflowExecutionResult = workflow.execute(request)
}

Workflow看起来像这样:
public class WorkflowInSeeSharpProject {

public execute(Request request) {

var retrieveCustomers = new RetrieveCustomers()
var retrieveCustomersResult = retrieveCustomers.retrieve()

// some code here
var createRequest = new CreateRequest()
var createRequestResult = createRequest.create(request)

// some code here
return workflowExecutionResult
}
}

所以在 C# 项目中每次 HomeControllerInSeeSharpProject被称为 WorkflowInSeeSharpProject 的新实例已创建并且所有域服务
也是新的,然后我可以确定状态不能在单独的线程之间共享。所以恐怕是因为我的 Scala Workflow和域服务的类型为 object而不是 class可能会出现两个请求被发送到 HomeController 的情况。
并且状态在这两个线程之间共享。

会是这样吗?我的应用程序不是线程安全的吗?

我读过 object Scala 中的 s 不是线程安全的,因为它们只有一个实例。但是我也读过,虽然
使用 val 它们不是线程安全的s 将使应用程序线程安全...

或者也许 Play本身有办法处理那个问题吗?

最佳答案

因为您使用的是编译时依赖注入(inject),所以您可以控制创建的实例数,在您的情况下为 HomeController只创建一次。随着请求的到来,这个单一实例将在线程之间共享,因此您确实必须确保它是线程安全的。 HomeController 的所有依赖还需要是线程安全的,因此 object Workflow必须是线程安全的。目前,Workflow不公开公开任何共享状态,因此它是线程安全的。一般情况下,val object 中的定义是 thread-safe .

有效HomeController表现得像一个单例,避免单例可能更安全。例如,默认情况下 Play Framework 使用 Guice依赖注入(inject),只要不是 @Singleton,每个请求都会创建一个新的 Controller 实例.一个动机是,正如 Nio's answer 所建议的那样,关于并发保护的担忧更少。 :

In general, it is probably best to not use @Singleton unless you have a fair understanding of immutability and thread-safety. If you think you have a use case for Singleton though just make sure you are protecting any shared state.

关于multithreading - 玩 Scala 和线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50619826/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com