仅仅传入参数并不会“保存”任何东西。从概念上讲,每个线程都有自己的arguments
作用域local
,它们对任何其他线程都不可见,并且在函数退出时不再存在。所以从这个角度来看,没有冲突。
此外,存储数据并不意味着将其保存到数据库表中。它指的是通过将数据存储在共享范围/对象/等中来维护状态的组件。“共享”意味着资源可以被其他线程访问,并且可能被多个线程同时修改,从而导致竞争条件.
例如,采用这个(人为的)组件函数,它在variables
作用域中“保存”信息。如果您每次都创建该组件的新实例,则该函数是安全的,因为每个请求都会获得它自己的实例和variables
要使用的范围的单独副本。
public numeric function doStuff( numeric num1, numeric num2 ) {
variables.firstNum = arguments.num1 * 12;
variables.secondNum = arguments.num2 * 10;
return variables.firstNum / variables.secondNum;
}
现在将相同的组件放入应用程序范围。它不再安全了。一旦您将其存储在application
范围内,该实例 - 及其variables
- 也将成为应用程序范围。因此,当函数将数据“保存”到variables
作用域时,它本质上是在更新一个application
变量。显然,这些不是线程安全的,因为所有请求都可以访问它们。因此,多个线程可以轻松地同时读取/修改相同的变量,从而导致竞争条件。
// "Essentially" becomes this ....
public numeric function doStuff( numeric num1, numeric num2 ) {
application.firstNum = arguments.num1 * 12;
application.secondNum = arguments.num2 * 10;
return application.firstNum / application.secondNum;
}
此外,正如James A Mohler 指出的那样,当您省略范围时,也会出现同样的问题。声明没有范围的函数变量不会使其成为函数的本地变量。它使其成为默认范围的一部分:-(variables
创建上述相同的线程安全问题)。当开发人员忘记限定单个查询变量甚至循环索引时,这种行为导致了许多线程错误。因此,请务必明确定义每个函数变量的范围。
// Implicitly creates "variables.firstNum" and "variables.secondNum"
public numeric function doStuff( numeric num1, numeric num2 ) {
firstNum = arguments.num1 * 12;
secondNum = arguments.num2 * 10;
return firstNum / secondNum;
}
除了添加锁定之外,这两个示例都可以通过显式使用local
范围来实现线程安全。通过将数据存储在瞬态local
范围内,它对其他线程不可见,并且一旦函数退出就不再存在。
public numeric function doStuff( numeric num1, numeric num2 ) {
local.firstNum = arguments.num1 * 12;
local.secondNum = arguments.num2 * 10;
return local.firstNum / local.secondNum;
}
显然还有其他情况需要考虑,例如通过引用传递的复杂对象或结构,以及这些对象是否在函数内被修改。但希望这能阐明“保存数据”的含义以及作用域如何在无状态组件(对application
范围安全)和有状态组件(不是)之间产生差异。
TL;博士;
在您的情况下,听起来大部分信息都没有共享,并且是请求级别的(用户信息、上传的图像等),因此存储在应用程序范围内可能是安全的。