The CFLOCK tag provides two types of locks to ensure the integrity of shared data:
An exclusive lock single-threads access to the CFML constructs in its body. Single-threaded access implies that the body of the tag can be executed by at most one request at a time. A request executing inside a CFLOCK tag has an "exclusive lock" on the tag. No other requests are allowed to start executing inside the tag while a request has an exclusive lock. ColdFusion issues exclusive locks on a first-come, first-served basis.
A read-only lock allows multiple requests to access the CFML constructs inside its body concurrently. Therefore, read-only locks should only be used when the shared data will only be read and not modified. If another request already has an exclusive lock on the shared data, the request will wait for the exclusive lock to be released before it can obtain it.
<CFLOCK TIMEOUT="timeout in seconds " SCOPE="Application" or "Server" or "Session" NAME="lockname" THROWONTIMEOUT="Yes/No" TYPE= "ReadOnly/Exclusive "> <!--- CFML to be synchronized ---> </CFLOCK>
Required. Specifies the maximum amount of time in seconds to wait to obtain an lock. If a lock can be obtained within the specified period, execution will continue inside the body of the tag. Otherwise, the behavior depends on the value of the THROWONTIMEOUT attribute.
Optional. Specifies the scope as one of the following: Application, Server, or Session. This attribute is mutually exclusive with the NAME attribute. See the Scope section for valuable information.
Optional. Specifies the name of the lock. Only one request will be able to execute inside a CFLOCK tag with a given name. Therefore, providing the NAME attribute allows for synchronizing access to the same resources from different parts of an application. Lock names are global to a ColdFusion server. They are shared between applications and user sessions, but not across clustered servers. This attribute is mutually exclusive with the SCOPE attribute. Therefore, do not specify the SCOPE attribute and the NAME attribute in the same tag. Note that the value of NAME cannot be an empty string.
Optional. Yes or No. Specifies how timeout conditions should be handled. If the value is Yes an exception will be generated to provide notification of the timeout. If the value is No execution continues past the </CFLOCK> tag. Default is Yes.
Optional. ReadOnly or Exclusive. Specifies the type of lock: read-only or exclusive. Default is Exclusive. A read-only lock allows more than one request to read shared data. An exclusive lock allows only one request to read or write to shared data. See the following Note.
Note | Limit the scope of code that updates shared data. Exclusive locks are required to ensure the integrity of these updates, but they have a significant impact on performance. Read-only locks are faster. If you have a performance-sensitive application, you should substitute read- only locks for exclusive locks wherever it is possible, for example, when reading shared data. |
ColdFusion Server is a multi-threaded web application server that can process multiple page requests at any given time. Use CFLOCK to guarantee that multiple concurrently executing requests do not manipulate shared data structures, files, or CFXs in an inconsistent manner. Note the following:
Whenever you display, set, or update variables, in one of the shared scopes, use the SCOPE attribute to identify the scope as Server, Application or Session.
Within the ColdFusion Administrator, the Locking page, under the Server section, allows you to set different characteristics of the locking schema according to scope.The following table shows which features are available for Server, Application, and Session scope.
Features | 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 |
Each feature that you select has tradeoffs.
For an analysis of best practices with respect to locking, please refer to Administering ColdFusion Server.
CFLOCK uses kernel level synchronization objects that are released automatically upon timeout and/or abnormal termination of the thread that owns them. Therefore, ColdFusion will never deadlock for an infinite period of time while processing a CFLOCK tag. However, very large timeouts can block request threads for long periods of time and thus radically decrease throughput. Always use the minimum timeout value allowed.
Another cause of blocked request threads is inconsistent nesting of CFLOCK tags and inconsistent naming of locks. If you are nesting locks, you and everyone accessing the locked variables must consistently nest CFLOCK tags in the same order . If everyone accessing locked variables does not adhere to these conventions, a deadlock can occur. A deadlock is a state in which no request can execute the locked section of the page. Thus, all requests to the protected section of the page are blocked until there is a timeout. The following tables show two scenarios that cause deadlocks.
Deadlock Scenario with Two Users | |
---|---|
User 1 | User 2 |
Locks the session scope . | Locks the application scope. |
Deadlock: Tries to lock application scope, but application scope already is locked by User 2. | Deadlock: Tries to lock the session scope, but session scope already is locked by User 1. |
Deadlock Scenario 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. |
<CFLOCK TIMEOUT="60" SCOPE="SESSION" TYPE="ReadOnly"> ............... <CFLOCK TIMEOUT="60" SCOPE="SESSION" TYPE="Exclusive"> ......... </CFLOCK> </CFLOCK>
Once a deadlock occurs neither of the users can do anything to break the deadlock, because the execution of their requests is blocked until the deadlock can be resolved by a lock timeout.
In order to avoid a deadlock, you and all who need to nest locks should do so in a well-specified order and name the locks consistently. In particular, if you need to lock access to the server, application, and session scopes, you must do so in the following order.
1. Lock the session scope. In the CFLOCK tag, indicate the scope by specifying "SESSION" as the value of the SCOPE attribute.
2. Lock the application scope. In the CFLOCK tag, indicate scope by specifying "APPLICATION" as the value of the SCOPE attribute.
3. Lock the server scope. In the CFLOCK tag, indicate the scope by specifying "SERVER" as the value of the SCOPE attribute.
4. Unlock the server scope.
5. Unlock the application scope.
6. Unlock the session scope.
Note | You can take out any pair of lock/unlock steps if you do not need to lock a particular scope. For example, you can take out Steps 3 and 4 if you do not need to lock the server scope. Similar rules apply for named locks. |
For complete usage information on CFLOCK, see Developing Web Applications with ColdFusion.
<!------------------------------------------------------------- This example shows how CFLOCK can be used to guarantee the consistency of data updates to variables in the Application, Server, and Session scopes. You should copy the following code into an Application.cfm file in the snippets directory. ---------------------------------------------------------------> <HTML> <HEAD> <TITLE>Define Session and Application Variables</TITLE> </HEAD> <BASEFONT FACE="Arial, Helvetica" SIZE=2> <BODY bgcolor="#FFFFD5"> <H3>CFAPPLICATION Example</H3> <P>CFAPPLICATION defines scoping for a ColdFusion application and enables or disables the storing of application and/or session variables. This tag is placed in a special file called Application.cfm that is run before any other CF template in a directory where the Application.cfm file appears.</P> <CFAPPLICATION NAME="ETurtle" SESSIONTIMEOUT=#CreateTimeSpan(0, 0, 0, 60)# SESSIONMANAGEMENT="yes"> <!---------------------------------------------------------------------- Initialize the session and application variables that will be used by E-Turtleneck. Use the 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 the application lock for the application variable. This variable keeps track of the total 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 is proud to say that we have sold #application.number# turtlenecks to date. </CFOUTPUT> </CFLOCK> <!---------------------------------------------------------------------- End of Application.cfm ------------------------------------------------------------------------ > <HEAD> <TITLE> CFLOCK Example </TITLE> </HEAD> <BASEFONT FACE="Arial, Helvetica" SIZE=2> <BODY bgcolor="#FFFFD5"> <H3>CFLOCK Example</H3> <CFIF IsDefined("form.submit")> <CFOUTPUT> Thank you for shopping E-Turtleneck. Today you have chosen a turtleneck in size <b>#form.size#</b> and in the 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 application variable application.number to find the total number of 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" METHOD="POST"> <P>Congratulations! You have just selected the longest wearing, most comfortable turtleneck in the world. Please indicate the color and size that you wish to buy.</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> </HTML>