Ouch, no!!! where/who told you to lock like that? You are making your
application single-threaded by doing that!
You need to var-scope the name of your query. This will make your DAO's read
thread-safe without syncronizing the calls (making it single threaded). The
ironic thing is that the read() method you posted ISN'T actually thread-safe,
because you didn't local var scope the "user" variable, thus it becomes an
instance variable of the DAO and then could be overwritten by another request
before your method gets a chance to return it. Here's an example of thread-safe
code:
<cffunction name="read" access="public" output="false" returntype="user">
<cfargument name="userID" type="numeric" required="yes">
<cfset var readuser = 0/>
<cfquery name="readuser" datasource="#variables.dsn#">
-- query user
</cfquery>
<cfif readuser.recordcount eq 1>
<cfreturn createObject("component","user").init(data)>
<cfelse>
<cfreturn createObject("component", "user").init()>
</cfif>
</cffunction>
So, no, you don't need to lock anywhere. The only reason to use a lock is when
you have a CFC instance stored in a shared scope (e.g. application scope) and
that CFC has properties (aka members aka instance data) which you need to read
and write after the object has been created. You'd need to syncronize the
access to those properties and thus you would use a named lock for the writes.
This usually isn't the case with shared-scope objects like gateways, DAOs,
services, etc because their methods don't modify instance data, thus you hardly
ever need locking in an OO CFC app.
Also, I'm not sure why your "gateway" would be calling a DAO. While it's just
naming, it would confuse me if I was looking at your code. Gateways provide
aggregated access to data (e.g., they return queries or similar datasets),
while DAOs provide persistance methods (CRUD) for individual objects.
Hope that helps...
Dave Ross
http://www.d-ross.org
http://www.coldspringframework.org
>Hello all,
>I have a question about thread safety and some objects I'm developing.
>Lets say for example that I've got 3 objects: user.cfc, userDAO.cfc,
>userGateway.cfc. My user.cfc acts as a bean, only populated with data
>from my userDAO object. The DAO object has basic querys to the db based
>on a user_id. It has code something like this:
>
><cffunction name="read" access="public" output="false"
>returntype="user">
> <cfargument name="userID" type="numeric" required="yes">
>
> <!--- lock for thread safety --->
> <cflock type="exclusive" timeout="120" name="readuser">
> <cfquery name="readuser" datasource="#variables.dsn#">
> -- query user
> </cfquery>
> </cflock>
>
> <cfif readuser.recordcount eq 1>
> <cfset user = createObject("component",
>"user").init(data)>
> <cfelse>
> <cfset user = createObject("component", "user").init()>
> </cfif>
>
> <cfreturn user>
></cffunction>
>
>
>The gateway object has code similar to the following:
>
><cffunction name="getUser">
> <cfargument name="user_id">
> <!--- should this read operation be locked? --->
> <cfreturn variables.userDAO.read(arguments.user_id)>
></cffunction>
>
>If I put the gateway object into the application scope, I know that I'll
>have to lock the query to get the user data from the userDAO, but is
>there going to be any issues with thread safety from the userGateway
>object when calling the getUser function?
>
>Rich Kroll
>Application Developer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
Message: http://www.houseoffusion.com/lists.cfm/link=i:4:239124
Archives: http://www.houseoffusion.com/cf_lists/threads.cfm/4
Subscription: http://www.houseoffusion.com/lists.cfm/link=s:4
Unsubscribe:
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=11502.10531.4
Donations & Support: http://www.houseoffusion.com/tiny.cfm/54