Thread safety example: Var scope your loop index in ColdFusion CFCs!

On the Dallas/Ft. Worth ColdFusion User Group email list, someone asked the question whether or not it is important to var scope your indexes in loops and items in loops of structures. While most agreed that it was important, one member contacted me off-list to make the case that Java actually manages the threading and it is a non-issue since ColdFusion 5. If you are new to this concept, the issue boils down to the fact that if you do not var scope local variables in a method, they are accessible and modifiable by other methods in the component since they reside in the variables scope. By adding “var” when setting variables in a method, you are protecting them from other processes outside that method. Example:

After attempting to make my case of why it is important (which fell on deaf ears) I thought it might be beneficial to write a short example that demonstrates a thread safety problem.

First, let’s create two components, ThreadKiller.cfc and ThreadSaver.cfc.

ThreadSaver.cfc:

<cfcomponent output="false">
	<cffunction name="init" access="public" output="false" returntype="ThreadSaver">
		<cfreturn this />
	</cffunction>
	<cffunction name="countUp" access="public" output="false" returntype="void">
		<cfscript>
		var i = "";
		for (i=1;i LTE 10;i=i+1) { countDown(); }
		</cfscript>
	</cffunction>
	<cffunction name="countDown" access="public" output="false" returntype="void">
		<cfscript>
		cool = "yeah";
		var i = "";
		for (i=10;i GTE 1;i=i-1) { /* nothing */ }
		</cfscript>
	</cffunction>
</cfcomponent>

ThreadKiller.cfc:

<cfcomponent output="false">
	<cffunction name="init" access="public" output="false" returntype="ThreadKiller">
		<cfreturn this />
	</cffunction>
	<cffunction name="countUp" access="public" output="false" returntype="void">
		<cfscript>
		for (i=1;i LTE 10;i=i+1) { countDown(); }
		</cfscript>
	</cffunction>
	<cffunction name="countDown" access="public" output="false" returntype="void">
		<cfscript>
		for (i=10;i GTE 1;i=i-1) { /* nothing */ }
		</cfscript>
	</cffunction>
</cfcomponent>

As you can see, these two components are virtually identical except for the use of the var scoping in the ThreadSaver.cfc methods. The downfall of ThreadKiller.cfc is the fact that in each iteration of the loop of the countUp() method, the called method countDown() will effectively overwrite the value of “i” setting it back to 1, creating an endless loop. In ThreadSaver.cfc, the two variables “i” are actually seperate containers and do not touch each other.

Now, let’s create our test page. Create a fiile named vartest.cfm in the same directory as the CFCs.

vartest.cfm:

<cfset Object = iif(StructKeyExists(url,"killit"),De("ThreadKiller"),De("ThreadSaver")) />
<cfset test = CreateObject("component",Object).init() />
<cfset test.countUp() />

done!

First, let’s run the “safe” test.  In your broswer, hit:
/vartest.cfm

When you run this, you will see that it did its work and then outputted “done!” on the screen.

Now we can do our “killer” test.  In your browser, hit:
/vartext.cfm?killit

Please note that this will spin up your processor until the request times out, and should only be done in a development environment in case you end up having to restart your ColdFusion instance.

When you run this, you can see that loop never completes and your server isn’t happy about it at all! Hopefully this will prove the point that it is definitely important to remember to var scope your index.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>