|
Comments
|
Today's Top SOA Links
BF on CF Lock It or Lose It
Lock It or Lose It
By: Ben Forta
Jul. 26, 2000 12:00 AM
We all know that locking is important. Most of us even understand why locks are needed. But exactly where to use a lock, which lock type to use and what code to put within the lock remains confusing at best. Part of the confusion stems from changes Allaire made in ColdFusion 4.5 that in turn changed the recommendations and suggested practices. Indeed, even my own recommendations changed with that release (as many of you CFUG members are quick to point out). And so, at the request of several of you, and because I've helped contribute to the confusion, I'll cover these topics in this column and try to set the record straight.
Variables
<CFSET first_name="Ben">The <CFSET> tag creates (or overwrites) a variable, in this case a variable named first_name. first_name can be thought of as a container located somewhere in the memory of the computer, a container that now has the name "Ben" in it. To access the data in the container you simply refer to the container by name, like this: <CFOUTPUT>#first_name#</CFOUTPUT>In this example I used a simple variable. I could just have easily placed an array or list in that container, or even data as complicated as an array of structures containing arrays of structures, and so on.
Regardless of the type of data, one thing is consistent: you refer to the container (the variable) by a unique name, and that name provides access to the contents of the container at the moment it's requested.
Understanding Threads
Simultaneous Variable Access
The variable first_name, created earlier, was created in the VARIABLES scope. As explained above, this scope is processed by a single thread, and as soon as that thread has completed processing the request, the variable is destroyed. As such, there is absolutely no way more than one request could access the data in the VARIABLES.first_name container at the same time. But other scopes behave differently. The following code creates a variable in the SESSION scope: <CFSET SESSION.first_name="Ben">As explained above, SESSION variables can indeed be processed by multiple threads at once. If you use frames, if the user hits the refresh button, if the underlying network makes retries - there are lots of conditions that could cause the same SESSION to be processed by more than one thread at any given time. This is where things get dangerous. Let's go back to our container analogy. If you were to put data into a container at the exact moment someone else was doing so, what would happen? Both writes couldn't occur at the same time, so something would get lost - or worse, the container itself could become corrupted. If the <CFSET> statement above was executed at the exact same time as another <CFSET> statement that was updating the same variable, you'd likely corrupt server memory. If you're lucky, you'll just throw an error, but you could also negatively impact server operation as a whole. And it's not just SESSION variables that are affected. APPLICATION and SERVER scope variables are even more susceptible to this corruption as they're always shared. (CLIENT variables, however, aren't susceptible as they're stored in a database; the database handles concurrency issues itself.)
Using Locks
In other words, locks can arbitrate code execution across multiple threads, pausing execution as needed. And yes, this could slow down your application, but considering the alternative it's a small price to pay. Accessing a variable (writing or reading) while it's being written by another thread is asking for trouble. The next code snippet sets the same SESSION variable once again, but this time locking it for the duration of the update: <CFLOCK SCOPE="SESSION" TYPE="EXCLUSIVE" TIMEOUT="10">Locking is implemented using the <CFLOCK> tag, and any code between the <CFLOCK> and </CFLOCK> tags will be locked. The SCOPE attribute specifies the scope to be locked by specifying SESSION as the scope. We're instructing ColdFusion to lock only the code execution for a particular SESSION. We wouldn't want to lock all sessions as that would cause other operations to pause unnecessarily (they wouldn't be updating this SESSION anyway). The TYPE attribute specifies the lock type. EXCLUSIVE means that no other operations on the specified SCOPE will be allowed while the lock is being processed. The TIMEOUT specifies the maximum time that ColdFusion should wait when trying to acquire a lock. If that timeout is reached before the lock can be acquired (perhaps because other threads have the same scope locked), the entire <CFLOCK> code block is skipped (and an exception is thrown). To lock the APPLICATION scope you'd simply specify SCOPE="APPLICATION". Doing so would lock the APPLICATION scope so any other attempt to access APPLICATION data would be paused. The same is true for SERVER. It's important to note that <CFLOCK> will do its job if all appropriate code is enclosed within <CFLOCK> tags. If somewhere in the code you had a <CFSET> statement that didn't use a <CFLOCK>, it could access the variable even though it was locked. For locking to work, all accesses must be managed by <CFLOCK> statements.
SCOPE vs NAME
ColdFusion also supports locking by NAME. Using this method, you provide a name to identify the activity performed in the locked code, and only locks with the same NAME will be locked. Exactly what operations are locked within the lock is entirely up to you. All <CFLOCK> does is ensure that no two blocks of code with the same NAME are executed at once. Using NAME gives you a greater level of control over lock granularity, but with that control comes additional risk. If you mistakenly use different names for two locks that access the same data, you won't be locking at all. The ability to lock code by scope was introduced in ColdFusion 4.5, and it's the preferred way to lock code that accesses potentially shared variables.
Read-Only Locks
Some languages support the use of constants, special variables that are actually not variable at all as they can't be changed. ColdFusion has no concept of constants, so CF developers typically create variables in the APPLICATION scope (usually in the APPLICATION.CFM file surrounded by a <CFIF NOT IsDefined()> check) and are careful never to overwrite them. If an application contained variables like this, variables that were never updated (after initial creation), you wouldn't really need to lock them at all. But you'd have to be 100% sure that an update wouldn't occur, realizing that there's nothing you can do programmatically to prevent that. What to do? Locking all read accesses (every time you refer to #SESSION.first_name#, for example) with exclusive locks imposes a significant performance loss, and the risk may not be worth it. So you could opt not to lock variable reads. But there's always the chance that someone will edit the code, and the variable that was never supposed to be updated...well, what if some new code now updated it? To address this problem, ColdFusion supports an additional lock type, READONLY. A READONLY lock doesn't actually lock anything unless an EXCLUSIVE lock is being processed at the same time. Only then will the READONLY lock pause until the EXCLUSIVE lock has completed. In other words, READONLY locks have no real performance hit associated with them. They are essentially ignored until an EXCLUSIVE lock is in effect.
Other Operations Needing Locks
In all of these examples, locking the code block can avoid concurrency problems. But instead of locking by SCOPE, these operations should be locked by NAME.
Locking Tips
The common theme is that locks should be used, but they must be used carefully. And careful use requires a good understanding of what locks are, what they do and how your application should use them. Locking is an important ColdFusion feature, and one that serious developers must use in their applications. Without locking there's a very real risk that data corruption will occur, and this can impact server stability. Incorrect lock use, of course, can bring your application to its knees. That fine line must be walked. Yes, there are performance penalties involved, but every decision involves some kind of trade-off. What you do is your choice. My advice? Lock it or lose it. Reader Feedback: Page 1 of 1
Your Feedback
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||