views:

564

answers:

4

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.

A: 

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.

Anne Porosoff
+5  A: 

You should use when reading and writing from things that chan 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.

Nathan Strutz
You might want to be cautious of exclusive scope wide locking -- it can quickly become a performance bottleneck.
modius
+2  A: 

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.

Ben Doom
+1  A: 

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)>
rip747