我何时应该使用范围锁定(应用程序,服务器等)与ColdFusion中的命名锁定?

时间:2008-11-17 20:07:20

标签: coldfusion locking shared-memory coldfusion-8

何时适合使用< cflock scope =“application”>或者它与< cflock name =“foo”>?相反?

具体来说,我对使用CFLock保护应用程序,会话或服务器范围中的共享对象感兴趣,但我也有兴趣了解ColdFusion中锁定的不同用法。

6 个答案:

答案 0 :(得分:10)

您应该在读取和写入可能在应用程序范围内发生变化的事物时使用。例如:

<cfquery name="application.myData">
    select * from myTable
</cfquery>

你想要用type =“exclusive”来锁定它。无论在何处使用application.myData,您都需要一个type =“readonly”锁。 Application.cfc的OnApplicationStart方法是个例外,它自动锁定。同样,在会话和服务器范围内使用相同的策略。

命名锁可让您更好地控制锁定策略。需要动态锁定命令时,请使用命名的cflock。例如:

<cflock name="write_file_#session.user_type#" type="exclusive">
    <cffile action="write" name="file_#session.user_type#" output="#content#" />
</cflock>

在此示例中,允许不同类型的用户同时写入文件,但具有相同 session.user_type 的用户必须彼此等待。此cflock有助于避免文件争用问题。

使用命名锁定的另一个原因是您不知道当前操作的范围。如果您在实例化的cfc中,您如何知道实例化的范围?变量?会议?应用?好的封装告诉我们,对象除了被告知之外什么都不知道。在CFC中,使用命名锁并在CFC之后命名它,或者根据您的用例将CFC和唯一实例变量命名。

答案 1 :(得分:2)

继续@Mr。 Nate说,每当你担心竞争条件时都要使用锁。例如,您可能希望锁定会话初始化,但不能锁定后续读取。同样,您可能希望锁定写入应用程序范围,但不能读取。

自引入线程安全共享变量作用域的CF6以来,锁定读取的效果要差得多。在过去的糟糕时期,如果你不小心,你可以同时读取和写入相同的内存地址。但是,由于CF成为Java驱动的,这不是问题。

正如他所演示的那样,命名锁对于锁定任何非作用域的东西很有用,比如文件读/写。

答案 2 :(得分:2)

建立在此处的其他建议。

老实说,既然cf8的出现,现在复制()可以复制对象,我只会在写入应用程序,会话或服务器范围时使用范围锁(顺便说一下,写入服务器范围是一个很大的没有 - 我的书中没有。)

如果你需要读取数据,我会使用duplicate()对数据进行深度复制到局部变量,并避免一起读取锁定。这样可以防止死锁。

<cflock scope="application" timeout="5" type="exlusive">
 <cfset application.data = {}>
 <cfset application.data.firstname = "tony">
</cflock>

<cfset variables.firstname = duplicate(application.data.firstname)>

答案 3 :(得分:1)

使用命名锁定的好时机就是当你有一个“事务”,你想要确保一次性发生,例如一次更新数据库中的几个表,或者当你只是想确保两个用户一次不更新相同的数据库记录,或者在读取或写入服务器上的文件时,一次可能有多个用户尝试访问它。

简单地说,任何时候如果两个请求同时尝试做同样的事情就会出现问题,然后在它周围放一个命名锁(或者如果它严格涉及会话,应用程序或服务器范围) ,然后使用范围锁。)

Ben Nadel曾发布一篇博客文章说:

  

“我看待它的方式,必须满足两个条件才能要求   使用CFLock:

     
      
  1. 正在访问或更新共享资源。
  2.   
  3. 必然存在竞争条件导致负面结果的可能性。“
  4.   

你甚至可以嵌套CFLOCK标签,例如在事务周围有一个命名锁,嵌套在内部的会话或应用程序作用域锁,但要小心这样做 - 如果你做错了,你可能会出现“死锁”的情况其中没有请求可以执行页面的锁定部分,并且可能会阻止对页面的锁定部分的所有请求,直到超时为止。 (ColdFusion手册描述了嵌套锁定的最佳实践。)

答案 4 :(得分:0)

通常,只要您在Application.cfc之外阅读或更改这些变量,就应该始终对会话,应用程序和服务器变量使用cflock,以防止竞争条件。这篇文章可能会有所帮助:

http://www.horwith.com/index.cfm/2008/4/28/cflock-explained

修改:为了进一步回答有关范围的问题,每当与共享资源进行交互时,我总是使用<cflock scope="application">(例如)。

答案 5 :(得分:0)

这是ColdFusion 8文档中的一个示例,该文档使用页面变量创建“本地标志”,可以在不锁定的情况下读取该标志,以查看应用程序变量是否已初始化。

这解决的问题是我们需要条件化排他锁,因为每次加载页面时都会运行它可能会因锁占用更多的处理时间而产生瓶颈。

我不知道自从有没有出现过更好的技术,但我认为无论如何我都会在这里发布。 ColdFusion文档通常不提供良好的代码,所以我很想知道是否有人能看到如何改进这些代码。

  • 我可能会将本地标志放在请求范围内,以便即使在自定义标签等中也可用。但是,它实际上只在app.cfm中需要,所以也许这是不必要的。
  • 我也会删除isDefined()以支持structKeyExists(),这样就不必循环遍历所有范围。
  • 我还会使用括号表示法来设置变量,以便保留大小写(例如application ['myDsn'] =“orders”)。它还可以更容易地发现变量写入,这比变量读取更重要。 (这只是我的偏好)

来源:http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=sharedVars_18.html

<!--- Initialize local flag to false. --->
<cfset app_is_initialized = False>
<!--- Get a readonly lock --->
<cflock scope="application" type="readonly">
    <!--- read init flag and store it in local variable --->
    <cfset app_is_initialized = IsDefined("APPLICATION.initialized")>
</cflock>
<!--- Check the local flag --->
<cfif not app_is_initialized >
<!--- Not initialized yet, get exclusive lock to write scope --->
    <cflock scope="application" type="exclusive">
        <!--- Check nonlocal flag since multiple requests could get to the
                exclusive lock --->
        <cfif not IsDefined("APPLICATION.initialized") >
            <!--- Do initializations --->
            <cfset APPLICATION.varible1 = someValue >
             ... 
            <!--- Set the Application scope initialization flag --->
            <cfset APPLICATION.initialized = "yes">
        </cfif>
    </cflock>
</cfif>