The cflock
tag controls simultaneous access to ColdFusion code. The cflock
tag enables you to:
Failure to use cflock
in these circumstances can result in data corruption and can result in hanging the ColdFusion Server. Symptoms of this corruption include the following:
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>
ColdFusion Server is a multithreaded Web application server that can process multiple page requests at a time. As a result, the server can attempt to access the same information simultaneously as the result of two or more requests. While it is safe to read data simultaneously, attempting to write data simultaneously or read and write it at the same time can result in corrupted memory and can cause the process to crash.
The cflock
tag enables you to ensure that concurrently executing requests do not access the same section of code simultaneously and thus manipulate shared data structures, files, or CFXs inconsistently. It is important to remember that cflock
protects code sections not variables.
The cflock
tag offers two modes of locking, specified by the type
attribute:
Enclose all code that creates or modifies Session, Application, or Server variables in exclusive cflock
tags.
cflock
tag body. Enclose code that reads or tests Session, Application, or Server variables in exclusive cflock
tags. You specify a read-only lock by setting the type="readOnly"
attribute in the cflock
tag.
The cflock
tag prevents simultaneous access to a sections of code, not variables. If you have two sections of code that access the same variable, they too must be synchronized to prevent them form running simultaneously. You do this by identifying the locks with either 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 |
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:
If multiple code sections share a lock, the following rules apply:
cflock
tag block with the type Exclusive is running, code in blocks with the same lock are not allowed run. They wait until the code with the Exclusive lock completes.
cflock
tag block with the type read-only is running, code in other blocks with the same lock and the read-only type can run, but any blocks with the exclusive type cannot run and wait until all code with the read-only lock completes.
The cflock
name
attribute provides a second mechanism for identifying 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. It 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 timeout period, ColdFusion generates an exception error, which you can handle using cftry
and cfcatch
.
If you set the cflock
throwOntTmeout
attribute to No, processing continues after the timeout at the line after the </cflock>
end tag.
Under normal circumstances it should not take more than a few seconds to obtain a lock. Very large timeouts can block request threads for long periods of time and radically decrease throughput. Always use the smallest timeout value that does not result in significant numbers of timeouts.
To prevent unnecessary timeouts, 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 perform a time-consuming activity outside of a cflock
tag and assign the results to a Variables scope variable, then assign the shared scope variable to the Variables scope variable's value inside a 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 illustrates this technique:
<cfquery name="Variables.qUser" datasource="#request.dsn#">
SELECT FirstName, LastName FROM Users WHERE UserID = #request.UserID# </cfquery> <cflock scope="Session" timeout="2" type="exclusive"> <cfset Session.qUser = Variables.qUser> </cflock>
You can specify several types of automatic locking and lock checking in ColdFusion Administrator. Use these options when you are developing your code and if you must maintain existing, poorly locked code.
The Locking page on the Server tab in the ColdFusion Administrator lets you specify the following for variables in each of the three shared memory scopes: Session, Application, and Server.
Selecting the No automatic checking or locking option results in the most efficient code, but requires you to follow the full rules of locking. You should only select this option after you finish debugging your program.
Full checking is very useful for debugging your code. You get errors to help indicate missing locks. You can leave this feature on in production code to protect against inadvertently unlocked variable accesses, but it adds processor overhead for checking all accesses to shared variables, and all locking problems cause exceptions.
Automatic read locking also adds overhead because ColdFusion must insert read locks and check variable access for locking. However, it can be useful if you already have a site that does not use locking properly. In this case, you must only lock all writes and do not have to add locks around all reads.
The ColdFusion Administrator also allows you to specify single-threaded sessions. If you select this option, each session is handled by a single thread in the ColdFusion Server. As a result, one request from the client must complete before the next one can begin. In this case, you do not need to lock Session variables, but the performance of frames-based pages might be reduced because it prevents simultaneous processing of requests from multiple frames.
Inconsistent nesting of cflock
tags and inconsistent naming of locks can cause deadlocks (blocked code). If you are nesting locks, you must consistently nest cflock
tags in the same order and use consistent lock scopes (or names).
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 table shows one scenario that would cause a deadlock:
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 is resolved by a lock timeout.
In addition, if you nest locks of different types, you can cause a deadlock. An example of this is nesting an exclusive lock inside a read lock of the same scope, or of the same name.
In order to avoid a deadlock, you should lock code sections 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.
cflock
tag, specify the scope as "session."
cflock
tag, specify the scope as "application."cflock
tag, specify the scope as "server."
Note You can skip any pair of lock/unlock steps in the preceding list if you do not need to lock a particular scope. For example, you can omit steps 3 and 4 if you do not need to lock the Server scope. |