我真的希望你能帮助我.我通常将会话变量读入局部变量,这样我就不必创建无限的读锁.但我遇到了一些有趣的行为.请注意,为简洁起见,我没有应用任何写锁:
考虑以下:
例1:
<cfset session.testvalue = 1 />
<cfset lcktestvalue = session.testvalue />
<cfoutput>#lcktestvalue#</cfoutput><br />
<cfset session.testvalue = 2 />
<cfoutput>#lcktestvalue#</cfoutput>
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
1
1
例2:
<cfset session.testvalue1.item = 1 />
<cfset lcktestvalue1 = session.testvalue1 />
<cfoutput>#lcktestvalue1.item#</cfoutput><br />
<cfset session.testvalue1.item = 2 />
<cfoutput>#lcktestvalue1.item#</cfoutput>
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
1
2
我试图弄清楚为什么第二个例子,更新'lcktestvalue1.item',当值只读一次?我希望示例1和2生成相同的输出,以下以生成第二个示例的输出:
例3:
<cfset session.testvalue1.item = 1 />
<cfset lcktestvalue1 = session.testvalue1 />
<cfoutput>#lcktestvalue1.item#</cfoutput><br />
<cfset session.testvalue1.item = 2 />
<cfset lcktestvalue1 = session.testvalue1 />
<cfoutput>#lcktestvalue1.item#</cfoutput>
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
1
2
我能想到的这种行为的唯一原因是第二个例子,它使用了一个结构内部的结构.但是,我无法扩展这个概念.你能?我真的需要理解这一点,因为我正在创建一个购物车,它广泛使用了示例2中的方法.它实际上工作正常,但我不确定为什么,我担心在负载下,它可能会失败?
感谢您提供的任何帮助.
因为您的第二个示例是从原始值到新值创建指针或引用.你可以想到它是两者之间的一个虚构的字符串,当一个被改变时 - 另一个也是如此.结构会发生这种情况.你可以通过使用副本解决这个问题.
但是注意!近十年来,不需要过度使用cflock会话/ app/server变量.您仍然需要担心竞争条件,但99%的情况下,这不是您的担忧.
查尔斯,这是预期的行为.结构和对象通过引用传递- 这意味着您实际上只是设置指向内存位置的指针以获取底层对象.当set语句处理原语(字符串,数字,日期等)时,它会将数据复制到新变量中 - 所以这样:
<Cfset session.testvalue = 1/>
<cfset testvalue = session.testvalue/>
Run Code Online (Sandbox Code Playgroud)
...实际创建2个位置,每个位置包含一个"1"
当你处理一个对象时(结构,组件,函数,查询等 - 任何不是原始的),如下所示:
<cfset session.testvalue.item1 = 1/>
<cfset testvalue = session.testvalue/>
Run Code Online (Sandbox Code Playgroud)
该variables.testvalue变量实际上是一个指针结构在Set语句创建(session.testvalue.item1隐含创建一个结构).
这是重要的基本内容 - 特别是在处理CFC,函数,应用程序范围等时.这篇关于Primitive vs复杂变量的文章更详细地解释了它.
它与锁定无关.除非你有一些可证明的竞争条件,否则你不需要过度锁定.
我会注意到你在这里的实践可能不是一个好主意 - 你应该将你的本地变量作为变量 .varName 任意方式,在这种情况下将会话变量推送到该范围并不会省去任何努力.
注意:当我写这篇文章的时候,Ray简明扼要地回答了这一点(当时我很啰嗦).
注2:在ColdFusion中有一个细微差别,有些人发现意外 - 数组按值传递(作为副本)而不是通过引用传递.这有时会让你失望 - 如果你曾经做过一系列的对象