¿Cuándo debo usar Scope Locking(Aplicación, Servidor, etc.) frente al bloqueo con nombre en ColdFusion?
shared-memory coldfusion-8 (6)
Continuando con lo que @Mr. Nate dijo, usa bloqueos siempre que te preocupen las condiciones de carrera. Por ejemplo, es posible que desee bloquear una inicialización de sesión, pero no lecturas posteriores. Del mismo modo, es posible que desee bloquear las escrituras en el alcance de la aplicación, pero no las lee.
Bloquear una lectura es mucho menos útil desde CF6, que introdujo ámbitos de variables compartidas seguros para subprocesos. En los viejos tiempos, si no tenías cuidado, podrías leer y escribir simultáneamente la misma dirección de memoria. Sin embargo, desde que CF se convirtió en Java, esto no es un problema.
Los bloqueos con nombre son útiles, como lo demostró, para bloquear todo lo que no tiene alcance, como leer / escribir archivos.
¿Cuándo es apropiado usar <cflock scope = "application"> o es ilk en lugar de <cflock name = "foo">?
Específicamente, estoy interesado en usar CFLock para proteger objetos compartidos en la aplicación, la sesión o los ámbitos del servidor, pero también estoy interesado en conocer los diferentes usos del bloqueo en ColdFusion.
Por lo general, siempre debe usar cflock para sesión, aplicación y servidor vars en cualquier momento que esté leyendo o cambiando esos valores fuera de Application.cfc para evitar condiciones de carrera. Aquí hay un artículo que puede ser útil:
http://www.horwith.com/index.cfm/2008/4/28/cflock-explained
Editar: Para responder mejor a su pregunta sobre el alcance, siempre uso <cflock scope="application">
(por ejemplo) siempre que interactúo con recursos compartidos.
construyendo sobre las otras sugerencias aquí.
para ser sincero, desde el advenimiento de cf8 y ahora que duplicar () puede duplicar objetos, solo usaría bloqueos de alcance al escribir en aplicación, sesión o alcance del servidor (por cierto, escribir en el alcance del servidor es un gran no-no en mi libro).
si necesita leer los datos, usaría duplicate () para hacer una copia profunda de los datos en una variable local y evitar el bloqueo de lectura. esto evitará estancamientos.
<cflock scope="application" timeout="5" type="exlusive">
<cfset application.data = {}>
<cfset application.data.firstname = "tony">
</cflock>
<cfset variables.firstname = duplicate(application.data.firstname)>
Debe usar al leer y escribir cosas que pueden cambiar en el alcance de la aplicación. Por ejemplo:
<cfquery name="application.myData">
select * from myTable
</cfquery>
Vas a querer bloquear eso con type = "exclusive". Donde sea que se use application.myData, necesita un bloqueo type = "readonly". La excepción es el método OnApplicationStart de Application.cfc, que se bloquea solo. Asimismo, use la misma estrategia con los ámbitos de sesión y servidor.
Los bloqueos con nombre le dan más control sobre su estrategia de bloqueo. Use un named cflock cuando necesite bloquear comandos dinámicamente. Por ejemplo:
<cflock name="write_file_#session.user_type#" type="exclusive">
<cffile action="write" name="file_#session.user_type#" output="#content#" />
</cflock>
En este ejemplo, los usuarios de diferentes tipos pueden escribir un archivo al mismo tiempo, pero los usuarios con el mismo session.user_type deben esperar el uno al otro. Este control ayuda a evitar problemas de contención de archivos.
Otra razón para utilizar un bloqueo con nombre es si no conoce el alcance de su operación actual. Si está en un CFC instanciado, ¿cómo sabe en qué ámbito se creó una instancia? Variables? ¿Sesión? ¿Solicitud? Una buena encapsulación nos enseña que los objetos no saben nada, excepto lo que se les ha dicho. Dentro de un CFC, use un candado con nombre y asígnele el nombre después del CFC, o el CFC y una variable de instancia única según su caso de uso.
Este es un ejemplo de la documentación de ColdFusion 8 que usa una variable de página para crear un "indicador local" que se puede leer sin bloqueo para ver si las variables de la aplicación se han inicializado.
Lo que sí soluciona esto es el hecho de que necesitamos condicionalizar el bloqueo exclusivo porque ejecutarlo cada vez que se carga una página puede crear cuellos de botella debido a que el bloqueo consume más tiempo de procesamiento.
No sé si han aparecido mejores técnicas desde que esto ocurrió, pero creo que lo publicaré aquí de todos modos. Los documentos de ColdFusion a menudo no proporcionan un buen código, por lo que estoy interesado en ver si alguien puede ver cómo se puede mejorar.
- Podría poner el indicador local en el alcance de la solicitud para que esté disponible incluso en etiquetas personalizadas, etc. Sin embargo, solo es realmente necesario en app.cfm, por lo que tal vez sea innecesario.
- También eliminaría isDefined () a favor de structKeyExists () para que no tenga que pasar por todos los ámbitos.
- También usaría la notación de corchetes para establecer las variables, de modo que las mayúsculas se conserven (por ejemplo, la aplicación [''myDsn''] = "orders"). También hace que sea más fácil detectar escrituras variables, que son un poco más importantes que las lecturas variables. (Esta es solo mi preferencia)
Fuente: http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=sharedVars_18.html
<!--- Initialize local flag to false. --->
<cfset app_is_initialized = False>
<!--- Get a readonly lock --->
<cflock scope="application" type="readonly">
<!--- read init flag and store it in local variable --->
<cfset app_is_initialized = IsDefined("APPLICATION.initialized")>
</cflock>
<!--- Check the local flag --->
<cfif not app_is_initialized >
<!--- Not initialized yet, get exclusive lock to write scope --->
<cflock scope="application" type="exclusive">
<!--- Check nonlocal flag since multiple requests could get to the
exclusive lock --->
<cfif not IsDefined("APPLICATION.initialized") >
<!--- Do initializations --->
<cfset APPLICATION.varible1 = someValue >
...
<!--- Set the Application scope initialization flag --->
<cfset APPLICATION.initialized = "yes">
</cfif>
</cflock>
</cfif>
Un buen momento para usar el bloqueo con nombre es cuando tiene una "transacción" que desea asegurarse de que ocurra todo de una vez, por ejemplo, actualizando varias tablas en una base de datos a la vez, o cuando simplemente quiere asegurarse de que dos usuarios no estén Actualizando el mismo registro de la base de datos a la vez, o leyendo o escribiendo en un archivo en el servidor que podría tener más de un usuario a la vez tratando de acceder a él.
En pocas palabras, cada vez que hay una situación en la que podría haber problemas si dos solicitudes intentaron hacer lo mismo al mismo tiempo, luego coloque un bloqueo con nombre (o si implica estrictamente la sesión, la aplicación o el alcance del servidor, luego use un cerrojo de alcance).
Ben Nadel publicó una entrada de blog una vez que decía:
"De la forma en que lo veo, se deben cumplir DOS condiciones para requerir el uso de CFLock:
- Se está accediendo o actualizando un recurso compartido.
- Debe existir la posibilidad de una condición de carrera que resulte en un resultado NEGATIVO ".
Incluso puede anidar etiquetas CFLOCK, como tener un bloqueo con nombre alrededor de una transacción, y bloqueos con ámbito de sesión o aplicación anidados en su interior, pero hágalo con precaución; si lo hace incorrectamente, podría tener una situación de "interbloqueo" donde no se solicite puede ejecutar la sección bloqueada de la página y todas las solicitudes a la sección bloqueada de una página pueden ser bloqueadas hasta que haya un tiempo de espera. (El manual de ColdFusion describe las mejores prácticas para el bloqueo anidado).