我什么时候应该在 ColdFusion 中使用范围锁定(应用程序、服务器等)与命名锁定?

发布于 2024-07-09 15:25:21 字数 192 浏览 9 评论 0 原文

什么时候适合使用 或者它与 相反?

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

When is it appropriate to use <cflock scope="application"> or it's ilk as opposed to <cflock name="foo">?

Specifically, I'm interested in using CFLock to protect shared objects in the application, session, or server scopes, but I'm also interested in finding out about different uses of locking in ColdFusion.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

谈情不如逗狗 2024-07-16 15:25:21

当读取和写入应用程序范围内可能更改的内容时,应该使用。 例如:

<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 和唯一实例变量命名,具体取决于您的用例。

You should use when reading and writing from things that can change in the application scope. For example:

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

You are going to want to lock that with type="exclusive". Wherever application.myData is used, you need a type="readonly" lock. The exception is Application.cfc's OnApplicationStart method, which locks itself. Likewise use the same strategy with the session and server scopes.

Named locks give you more control over your locking strategy. Use a named cflock when you need to lock commands dynamically. For example:

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

In this example, users of different types are allowed to write a file at the same time, but users with the same session.user_type must wait for each other. This cflock helps avoid file contention issues.

Another reason to use a named lock is if you do not know the scope of your current operation. If you are in an instantiated cfc, how do you know what scope you were instantiated into? Variables? Session? Application? Good encapsulation teaches us that objects do not know anything except what they have been told. Inside a CFC, use a named lock and name it after the CFC, or the CFC and a unique instance variable depending on your use case.

涫野音 2024-07-16 15:25:21

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

自 CF6 引入线程安全共享变量作用域以来,锁定读取的用处就大大减少了。 在过去的糟糕日子里,如果你不小心,你可能会同时读取和写入同一个内存地址。 然而,自从 CF 成为 Java 驱动的之后,这就不再是问题了。

正如他所演示的,命名锁对于锁定任何未限定范围的内容非常有用,例如文件读/写。

Continuing with what @Mr. Nate said, use locks whenever you are concerned about race conditions. For example, you may want to lock a session initialization, but not subsequent reads. Similarly, you may want to lock writes to the application scope, but not reads.

Locking a read is a lot less useful since CF6, which introduced thread-safe shared variable scopes. In the bad old days, if you were not careful, you could be simultaneously reading and writing the same memory address. However, since CF became Java-powered, this is not a problem.

Named locks are useful, as he demonstrated, for locking anything that is not scoped, like file read/writes.

初懵 2024-07-16 15:25:21

建立在此处的其他建议之上。

老实说,自从 cf8 出现以来,duplicate() 可以复制对象,我只会在写入应用程序、会话或服务器作用域时使用作用域锁(顺便说一句,写入服务器作用域是我的一大禁忌)书)。

如果您需要读出数据,我会使用duplicate()将数据深度复制到局部变量并避免读锁。 这将防止死锁。

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

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

building upon the other suggestions here.

to be honest, since the advent of cf8 and now that duplicate() can duplicate objects, i would only use scope locks when writing to application, session or server scope (btw, writing to the server scope is a big no-no in my book).

if you need to read the data out, i would use duplicate() to do a deep copy of the data to a local variable and avoid the read lock all together. this will prevent deadlocks.

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

<cfset variables.firstname = duplicate(application.data.firstname)>
失退 2024-07-16 15:25:21

使用命名锁定的最佳时机是当您想要确保一次完成一项“事务”时,例如一次更新数据库中的多个表,或者当您只是想确保两个用户同时进行时一次不更新相同的数据库记录,或者在读取或写入服务器上的文件时,一次可能有多个用户尝试访问该文件。

简而言之,任何时候如果两个请求尝试同时执行相同的操作,则可能会出现问题,然后在其周围放置一个命名锁(或者如果它严格涉及会话、应用程序或服务器范围,则使用作用域锁)。

本·纳德尔 (Ben Nadel) 曾发表过一篇博客文章,其中写道:

“在我看来,必须满足两个条件才能要求
CFLock的使用:

  1. 正在访问或更新共享资源。
  2. 一定存在竞争条件导致负面结果的可能性。”

您甚至可以嵌套 CFLOCK 标记,例如在事务周围有一个命名锁,以及嵌套在其中的会话或应用程序范围的锁,但请谨慎执行 - 如果如果你做错了,你可能会遇到“死锁”情况,没有请求可以执行页面的锁定部分,并且对页面锁定部分的所有请求都可能被阻止,直到超时(ColdFusion 手册描述得最好)。嵌套锁定的实践。)

A great time to use named locking is when you have a "transaction" that you want to make sure happens all in one go, for example updating several tables in a database at once, or when you simply want to make sure that two users aren't updating the same database record at a time, or when reading or writing to a file on the server that might have more than one user at a time trying to access it.

Simply put, anytime there is a situation where there could be problems if two requests tried to do the same thing at the same time, then put a named lock around it (or if it strictly involves the session, application or server scope, then use a scoped lock).

Ben Nadel posted a blog entry once that said:

"The way I see it, TWO conditions must be met in order to require the
use of CFLock:

  1. A shared resource is being accessed or updated.
  2. There must be the possibility of a race condition resulting in a NEGATIVE outcome."

You can even nest CFLOCK tags, such as have a named lock around a transaction, and session or application scoped locks nested inside, but do so with caution -- if you do it wrong, you could have a "deadlock" situation where no request can execute the locked section of the page and all the requests to the locked section of a page might be blocked until there is a timeout. (The ColdFusion manual describes best practices for nested locking.)

把昨日还给我 2024-07-16 15:25:21

通常,每当您在 Application.cfc 之外读取或更改这些变量时,您都应该始终对会话、应用程序和服务器变量使用 cflock,以防止竞争条件。 这是一篇可能有用的文章:

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

编辑:为了进一步回答您有关范围的问题,我总是使用 (例如)每当与共享资源交互时。

Typically you should always use cflock for session, application and server vars any time you're reading or changing those vars outside of an Application.cfc so as to prevent race-conditions. Here's an article that may be helpful:

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

Edit: To further answer your question about scope, I always use <cflock scope="application"> (for example) whenever interacting with shared resources.

左秋 2024-07-16 15:25:21

这是 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>

This is an example from the ColdFusion 8 documentation that uses a page variable to create a "local flag" that can be read without locking to see if the application variables have been initialized.

What this does address is the fact that we need to conditionalize the exclusive lock because running it every time a page is loaded may create bottlenecks due to the lock taking up more processing time.

I don't know if better techniques have appeared since this has, but I figure I'll post it here anyway. The ColdFusion docs often don't provide good code, so I'm interested to see if anyone can see how this one can be improved.

  • I might put the local flag in the request scope so that it is available even in custom tags, etc. However, it's really only needed in app.cfm, so maybe that's unnecessary.
  • I also would remove isDefined() in favor of structKeyExists() so that it doesn't have to cycle through all the scopes.
  • I would also use bracket notation to set variables, so that capitalization is preserved (e.g. application['myDsn'] = "orders"). It also makes it easier to spot variable writes, which are a bit more important than variable reads. (This one's just my preference)

Source: 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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文