CFLOCK  
Description

Ensures the integrity of shared data. Instantiates the following kinds of locks:

  • Exclusive: allows single-thread access to the CFML constructs in its body. The tag body can be executed by one request at a time. No other requests can start executing within the tag while a request has an exclusive lock. ColdFusion issues exclusive locks on a first-come, first-served basis.
  • Read-only: allows multiple requests to access CFML constructs within the tag body concurrently. Use a read-only lock only when shared data is read and not modified. If another request has an exclusive lock on shared data, the new request waits for the exclusive lock to be released.
 
Category

Application framework tags

 
Syntax
    <cflock 
   timeout = "timeout in seconds "
   scope = "Application" or "Server" or "Session"
   name = "lockname" 
   throwOnTimeout = "Yes" or "No"
   type = "readOnly" or "exclusive "> 
   <!--- CFML to be synchronized ---> 
</cflock>

  
 
See also

cfapplication, cfassociate, cfmodule

Note: Limit the scope of code that updates shared data structures, files, and CFXs. Exclusive locks are required to ensure the integrity of updates, but read-only locks are faster. In a performance-sensitive application, substitute read-only locks for exclusive locks where possible; for example, when reading shared data.
 
Usage

ColdFusion Server is a multithreaded server; it can process multiple page requests at a time. USe the cflock tag for these purposes:

  • To ensure that modifications to shared data and objects made in concurrently executing requests occur sequentially.
  • Around file manipulation constructs, to ensure that file updates do not fail because files are open for writing by other applications or tags.
  • Around CFX invocations, to ensure that ColdFusion can safely invoke CFXs that are not implemented in a thread-safe manner. (This applies only to CFXs developed in C++ using the CFAPI.)

To work safely with ColdFusion, a C++ CFX that maintains and manipulates shared (global) data structures must be made thread-safe; however, this requires advanced knowledge. You can use a CFML custom tag wrapper around a CFX to make its invocation thread-safe.

 
Scope

When you display, set, or update variables in a shared scope, use the scope attribute to identify the scope as Server, Application or Session.

In the ColdFusion Administrator, Server section, the Locking page sets locking options according to scope. The following features are available for Server, Application, and Session scope:

Availability
Feature Server Application Session

No automatic checking or locking

Yes

Yes

Yes

Full checking

Yes

Yes

Yes

Automatic read locking

Yes

Yes

Yes

Single threaded sessions

 

 

Yes

These feature have the following tradeoffs:

  • No automatic checking or locking: Reads and writes are not locked nor checked for correct protection. Select this only if you have run with full checking and know that there are no errors to handle, and that all locking is handled programmatically. This provides the fastest performance.
  • Full checking: All unlocked accesses are detected. Select this when in debug mode. This slows performance.
  • Automatic read locking: Reads are locked. Unlocked writes cause an error. This feature slows performance considerably.
  • Single-threaded sessions: The request must finish before another request for the same session is processed. This feature might slow performance, depending on the request pattern. For example, the total response time might increase if an application has multiple frames that can be refreshed at once, causing multiple requests to queue.

For more information, see Administering ColdFusion MX.

If you create a lock with the name attribute, and enable full lock checking in the ColdFusion Administrator, ColdFusion returns an error.

Do not specify full checking for a lock in its own scope; for example, if the lock is in the Application scope, do not specify full checking for the Application scope.

 
Deadlocks

A deadlock is a state in which no request can execute the locked section of a page. Once a deadlock occurs, neither user can break it, because all requests to the protected section of the page are blocked until the deadlock can be resolved by a lock timeout.

The cflock tag uses kernel level synchronization objects that are released automatically upon timeout and/or the abnormal termination of the thread that owns them. Therefore, while processing a cflock tag, ColdFusion never deadlocks for an infinite period of time. However, very large timeouts can block request threads for long periods, and radically decrease throughput. To prevent this, always use the minimum timeout value.

Another cause of blocked request threads is inconsistent nesting of cflock tags and inconsistent naming of locks. If you nest locks, everyone accessing the locked variables must consistently nest cflock tags in the same order. Otherwise, a deadlock can occur.

These examples show situations that cause deadlocks:

Example deadlock with two users
User 1 User 2

Locks the session scope.

Locks the Application scope.

Deadlock: Tries to lock the Application scope, but it is already locked by User 2.

Deadlock: Tries to lock the Session scope, but it is already locked by User 1.

The following deadlock could occur if you tried to nest a write lock after a read lock:

Example deadlock with one user
User 1

Locks the Session scope with a read lock.

Attempts to lock the Session scope with an exclusive lock.

Deadlock: Attempts to lock the Session scope with an exclusive lock, but cannot because the scope is already locked for reading.

The following code shows this scenario:

<cflock timeout = "60" scope = "SESSION" type = "readOnly">
   ...............
   <cflock timeout = "60" scope = "SESSION" type = "Exclusive">
   .........
   </cflock>
</cflock>

To avoid a deadlock, everyone who nests locks must do so in a well-specified order and name the locks consistently. If you must lock access to the Server, Application, and Session scopes, you must do so in this order:

  1. Lock the Session scope. In the cflock tag, specify scope = "session".
  2. Lock the Application scope. In the cflock tag, specify scope = "Application".
  3. Lock the Server scope. In the cflock tag, specify scope = "server".
  4. Unlock the Server scope.
  5. Unlock the Application scope.
  6. Unlock the Session scope.
Note: If you do not have to lock a scope, you can skip any pair of these lock/unlock steps. For example, if you do not have to lock the Server scope, you can skip Steps 3 and 4. Similar rules apply for named locks.

For more information, see the following:

  • Developing ColdFusion MX Applications with CFML
  • Article #20370, ColdFusion Locking Best Practices, on the Macromedia website at http://www.macromedia.com/support/service/.
 
Example
<!--- This example shows how cflock can guarantee consistency of data updates
to variables in the Application, Server, and Session scopes. --->
<!----  Copy the following code into an Application.cfm file in the application 
root directory. ----->
<!-------------------------------   beginning of Application.cfm code 
   <h3>cfapplication Example</h3>
   <p>cfapplication defines scoping for a ColdFusion application and 
enables or disables storing of application and session variables.
Put this tag in a special file called Application.cfm. It is run before 
any other CF page in its directory.</p>
   <cfapplication name = "ETurtle" 
sessionTimeout = #CreateTimeSpan(0,0, 0, 60)# 
sessionManagement = "Yes">
<!--- Initialize session and application variables used by E-Turtleneck. 
Use session scope for the session variables. ---> 
   <cflock scope = "Session" 
      timeout = "30" type = "Exclusive">
      <cfif NOT IsDefined("session.size")>
         <cfset session.size = "">
      </cfif>
      <cfif NOT IsDefined("session.color")>
         <cfset session.color = "">
      </cfif>
   </cflock>
<!--- Use application lock for application variable. Variable keeps track 
of number of turtlenecks sold. The application lock should have 
the same name as specified in the cfapplication tag. ---->
   <cflock scope = "Application"       timeout = "30" type = "Exclusive">
      <cfif NOT IsDefined("application.number")>
         <cfset application.number = 1>
      </cfif>
   </cflock>
   <cflock scope = "Application" timeout = "30" type = "readOnly">
      <cfoutput>
         E-Turtleneck has sold #application.number# turtlenecks to date.
      </cfoutput>
  </cflock>
-------------------- End of Application.cfm ----------------------->    
<h3>cflock Example</h3>
<cfif IsDefined("form.submit")>
   <cfoutput>
      Thanks for shopping E-Turtleneck. You chose size <b>#form.size#</b>, 
color <b>#form.color#</b>.    </cfoutput>
   <!---    Lock session variables to assign form values to them. ----> 
   <cflock scope = "Session" timeout = "30" type = "Exclusive">
      <cfparam name = session.size Default = #form.size#>
      <cfparam name = session.color Default = #form.color#>
   </cflock>
   <!---- Lock variable application.number to find total turtlenecks sold. ---> 
   <cflock scope = "Application" timeout = "30" type = "Exclusive">
      <cfset application.number = application.number + 1>
   </cflock>
<cfelse><!--- Show the form only if it has not been submitted. --->
   <form action = "cflock.cfm">
   <p>Congratulations! You selected the most comfortable turtleneck in the world.
Please select color and size.</p> 
   <table cellspacing = "2" cellpadding = "2" border = "0">
      <tr>
         <td>Select a color.</td>
         <td><select type = "Text" name = "color">
               <option>red
               <option>white
               <option>blue
               <option>turquoise
               <option>black
               <option>forest green
            </select>
         </td>
      </tr>
      <tr>
         <td>Select a size.</td>
         <td><select type = "Text" name = "size" >
               <option>XXsmall
               <option>Xsmall
               <option>small
               <option>medium
               <option>large
               <option>Xlarge
            </select>
         </td>
      </tr>
      <tr>
         <td>Press Submit when you are finished making your selection.</td>
         <td><input type = "Submit" name = "submit" value = "Submit"> </td>
      </tr>
   </table>
   </form>
</cfif>
TIMEOUT  
  Required
 

Maximum length of time, in seconds, to wait to obtain a lock. If lock obtained, tag execution continues. Otherwise, behavior depends on throwOnTimeout attribute value.

SCOPE  
  Optional
 

Mutually exclusive with the name attribute.

  • Application
  • Server
  • Session
NAME  
  Optional
 

Lock name. Only one request can execute within this tag with a given name. Permits synchronizing access to resources from different parts of an application. Lock names are global to a ColdFusion server. They are shared among applications and user sessions, but not clustered servers. Mutually exclusive with the scope attribute. Cannot be an empty string.

THROWONTIMEOUT  
  Optional
 
Default value: "Yes"

How timeout conditions are handled.

  • Yes: exception is generated for the timeout.
  • No: execution continues past this tag.
TYPE  
  Optional
 
Default value: "Exclusive"
  • read-only: lets more than one request read shared data.
  • exclusive: lets one request read or write shared data.