The cflock
tag ensures that concurrently executing requests do not run the same section of code simultaneously and thus manipulate shared data structures, files, or CFX tags inconsistently. It is important to remember that cflock
protects code sections that access or set data, not the variables themselves.
You protect access to code by surrounding it in a cflock
tag; for example:
<cflock scope="Application" timeout="10" type="Exclusive"> <cfif not IsDefined("Application.number")> <cfset Application.number = 1> </cfif> </cflock>
The cflock
tag offers two modes of locking, specified by the type
attribute:
Exclusive locks (the default lock type) Allow only one request to process the locked code. No other requests can run code inside the tag while a request has an exclusive lock.
Enclose all code that creates or modifies session, application, or server variables in exclusive cflock
tags.
Read-only locks Allow multiple requests to execute concurrently if no exclusive locks with the same scope or name are executing. No requests can run code inside the tag while a request has an exclusive lock.
Enclose code that only reads or tests session, application, or server variables in read-only cflock
tags. You specify a read-only lock by setting the type="readOnly"
attribute in the cflock
tag, for example:
<cflock scope="Application" timeout="10" type="readOnly"> <cfif IsDefined("Application.dailyMessage")> <cfoutput>#Application.dailyMessage#<br></cfoutput> </cfif> </cflock>
Although ColdFusion does not prevent you from setting shared variables inside read-only lock tag, doing so loses the advantages of locking. As a result, you must be careful not to set any session, application, or server variables inside a read-only cflock
tag body.
Note: You cannot upgrade or downgrade a lock from one type to another. In other words, do not nest an exclusive lock in a read-only lock of the same name or scope; the exclusive lock will always time out. Also, do not nest a read-only lock inside an exclusive lock with the same name or scope; doing so has no effect.
The cflock
tag prevents simultaneous access to sections of code, not to variables. If you have two sections of code that access the same variable, they must be synchronized to prevent them from running simultaneously. You do this by identifying the locks with the same scope
or name
attributes.
Note: ColdFusion does not require you to identify exclusive locks. If you omit the identifier, the lock is anonymous and you cannot synchronize the code in the cflock
tag block with any other code. Anonymous locks do not cause errors when they protect a resource that is used in a single code block, but they are bad programming practice. You must always identify read-only locks.
When the code that you are locking accesses session, application, or server variables, synchronize access by using the cflock
scope
attribute.
You can set the attribute to any of the following values:
Scope | Meaning |
---|---|
Server |
All code sections with this attribute on the server share a single lock. |
Application |
All code sections with this attribute in the same application share a single lock. |
Session |
All code sections with this attribute that run in the same session of an application share a single lock. |
If multiple code sections share a lock, the following rules apply:
cflock
tag block with the type
attribute set to Exclusive
, code in cflock
tag blocks with the same scope
attribute is not allowed to run. They wait until the code with the exclusive lock completes.
cflock
tag block with the type readOnly
is running, code in other cflock
tag blocks with the same scope
attribute and the readOnly
type
attribute can run, but any blocks with the same scope
attribute and an Exclusive
type cannot run and must wait until all code with the read-only lock completes. However, if a read-only lock is active and code with an exclusive lock with the same scope or name is waiting to execute, read-only requests using the same scope or name that are made after the exclusive request is queued must wait until code with the exclusive lock executes and completes.
The cflock
name
attribute provides a second way to identify locks. Use this attribute when you use locks to protect code that manges file access or calls non-thread-safe CFX code.
When you use the name
attribute, specify the same name for each section of code that accesses a specific file or a specific CFX tag.
You must include a timeout
attribute in your cflock
tag. The timeout
attribute specifies the maximum time, in seconds, to wait to obtain the lock if it is not available. By default, if the lock does not become available within the time-out period, ColdFusion generates a Lock type exception error, which you can handle using cftry
and cfcatch
tags.
If you set the cflock
throwOnTimeout
attribute to No, processing continues after the time-out at the line after the </cflock>
end tag. Code in the cflock
tag body does not run if the time-out occurs before ColdFusion can acquire the lock. Therefore, never use the throwOnTimeout
attribute for CFML that must run.
Normally, it does not take more than a few seconds to obtain a lock. Very large time-outs can block request threads for long periods of time and radically decrease throughput. Always use the smallest time-out value that does not result in a significant number of time-outs.
To prevent unnecessary time-outs, lock the minimum amount of code possible. Whenever possible, lock only code that sets or reads variables, not business logic or database queries. One useful technique is to do the following:
cflock
tag
cflock
block.
For example, if you want to assign the results of a query to a session variable, first get the query results using a Variables scope variable in unlocked code. Then, assign the query results to a session variable inside a locked code section. The following code shows this technique:
<cfquery name="Variables.qUser" datasource="#request.dsn#"> SELECT FirstName, LastName FROM Users WHERE UserID = #request.UserID# </cfquery> <cflock scope="Session" timeout="5" type="exclusive"> <cfset Session.qUser = Variables.qUser> </cflock>