2008-11-17 5 views
11

Quand est-il approprié d'utiliser < cflock scope = "application" > ou est-il par opposition à < cflock name = "foo" >? Plus précisément, je suis intéressé par l'utilisation de CFLock pour protéger les objets partagés dans les applications, les sessions ou les portées de serveurs, mais je suis également intéressé par les différentes utilisations du verrouillage dans ColdFusion.Quand devrais-je utiliser Scope Locking (Application, Serveur, etc ...) vs verrouillage nommé dans ColdFusion?

Répondre

10

Vous devez utiliser lors de la lecture et de l'écriture des éléments susceptibles de changer dans la portée de l'application. Par exemple:

<cfquery name="application.myData"> 
    select * from myTable 
</cfquery> 

Vous allez vouloir verrouiller cela avec type = "exclusif". Partout où application.myData est utilisée, vous avez besoin d'un verrou type = "readonly". L'exception est la méthode OnApplicationStart de Application.cfc, qui se verrouille elle-même. Utilisez également la même stratégie avec les étendues de session et de serveur.

Les verrous nommés vous donnent plus de contrôle sur votre stratégie de verrouillage. Utilisez un cflock nommé lorsque vous avez besoin de verrouiller les commandes dynamiquement. Par exemple:

<cflock name="write_file_#session.user_type#" type="exclusive"> 
    <cffile action="write" name="file_#session.user_type#" output="#content#" /> 
</cflock> 

Dans cet exemple, les utilisateurs de différents types sont autorisés à écrire un fichier en même temps, mais les utilisateurs avec le même session.user_type doivent attendre les uns des autres. Ce cflock permet d'éviter les problèmes de conflit de fichiers.

Une autre raison d'utiliser un verrou nommé est si vous ne connaissez pas la portée de votre opération en cours. Si vous êtes dans un cfc instancié, comment savez-vous dans quelle portée vous avez été instancié? Variables Session? Application? Une bonne encapsulation nous enseigne que les objets ne savent rien sauf ce qu'on leur a dit. Dans un CFC, utilisez un verrou nommé et nommez-le après le CFC, ou le CFC et une variable d'instance unique en fonction de votre cas d'utilisation.

+0

Vous voudrez peut-être prudent de portée large verrouillage exclusif - il peut rapidement devenir un goulot d'étranglement. – modius

0

En règle générale, vous devez toujours utiliser cflock pour les variables de session, d'application et de serveur chaque fois que vous lisez ou modifiez ces variables à l'extérieur d'Application.cfc afin d'empêcher les conditions de concurrence. Voici un article qui peut être utile:

http://www.horwith.com/index.cfm/2008/4/28/cflock-explained

Edit: Pour mieux répondre à votre question sur la portée, je l'utilise toujours <cflock scope="application"> (par exemple) à chaque fois que l'interaction avec les ressources partagées.

2

Poursuivre avec ce que @Mr. Nate a dit, utilisez des verrous lorsque vous êtes préoccupé par les conditions de course. Par exemple, vous pouvez verrouiller une initialisation de session, mais pas les lectures suivantes. De même, vous pouvez verrouiller les écritures dans la portée de l'application, mais pas les lectures.

Verrouiller une lecture est beaucoup moins utile depuis CF6, qui a introduit des étendues de variables partagées sans risque pour les threads. Dans le mauvais vieux temps, si vous ne faisiez pas attention, vous pourriez lire et écrire simultanément la même adresse mémoire. Cependant, depuis CF est devenu Java, ce n'est pas un problème.

Les verrous nommés sont utiles, comme il l'a démontré, pour verrouiller tout ce qui n'est pas étendu, comme lire/écrire des fichiers.

2

en suivant les autres suggestions ici.Pour être honnête, depuis l'avènement de cf8 et maintenant que duplicate() peut dupliquer des objets, je n'utiliserais que des verrous de portée lors de l'écriture sur une application, une session ou une portée de serveur (btw, écrire à la portée du serveur -non dans mon livre).

Si vous avez besoin de lire les données, je voudrais utiliser duplicate() pour faire une copie profonde des données dans une variable locale et éviter le verrouillage de lecture tous ensemble. Cela permettra d'éviter les blocages.

<cflock scope="application" timeout="5" type="exlusive"> 
<cfset application.data = {}> 
<cfset application.data.firstname = "tony"> 
</cflock> 

<cfset variables.firstname = duplicate(application.data.firstname)> 
1

Un grand moment d'utiliser le verrouillage nommé est quand vous avez une « transaction » que vous voulez vous assurer que se passe en une seule fois, par exemple la mise à jour plusieurs tables dans une base de données à la fois, ou si vous voulez simplement pour vous assurer que deux utilisateurs ne mettent pas à jour le même enregistrement de base de données à la fois, ou lorsqu'ils lisent ou écrivent dans un fichier sur le serveur qui pourrait avoir plus d'un utilisateur à la fois essayant d'y accéder. En d'autres termes, chaque fois qu'il y a une situation où il pourrait y avoir des problèmes si deux demandes essayaient de faire la même chose en même temps, alors mettez un verrou nommé autour (ou si cela implique strictement la session, l'application ou le serveur portée, puis utilisez un verrou de portée).

Ben Nadel a posté une entrée de blog une fois que dit:

« La façon dont je le vois, deux conditions doivent être remplies afin d'exiger l' utilisation de cflock:

  1. A partagé la ressource est en cours d'accès ou mise à jour
  2. Il doit y avoir la possibilité d'une condition de concurrence entraînant un résultat NÉGATIF. "

Vous pouvez même imbriquer les balises cflock, comme un verrou nommé autour d'une transaction, et se verrouille scopes session ou l'application imbriquées à l'intérieur, mais le faire avec prudence - si vous le faites mal, vous pourriez avoir une situation d'interblocage où aucune requête ne peut exécuter la section verrouillée de la page et toutes les demandes à la section verrouillée d'une page peuvent être bloquées jusqu'à ce qu'il y ait un délai d'expiration. (Le manuel de ColdFusion décrit les meilleures pratiques pour le verrouillage imbriqué.)

0

Ceci est un exemple de la documentation de ColdFusion 8 qui utilise une variable de page pour créer un "indicateur local" qui peut être lu sans verrouillage pour voir si les variables d'application ont été initialisé. Ce problème est dû au fait que nous devons conditionnaliser le verrou exclusif, car l'exécuter chaque fois qu'une page est chargée peut créer des goulets d'étranglement car le verrou prend plus de temps de traitement.

Je ne sais pas si de meilleures techniques sont apparues depuis, mais je pense que je les publierai quand même. Les documents ColdFusion ne fournissent souvent pas de code correct, donc je suis intéressé de voir si quelqu'un peut voir comment celui-ci peut être amélioré.

  • je pourrais mettre le drapeau locale dans le cadre de la demande pour qu'il soit disponible même dans des balises personnalisées, etc. Cependant, il est vraiment nécessaire que dans app.cfm, alors peut-être que est inutile.
  • Je voudrais également supprimer isDefined() en faveur de structKeyExists() afin qu'il n'a pas à parcourir toutes les étendues.
  • Je voudrais également utiliser la notation de parenthèse pour définir des variables, de sorte que la capitalisation est préservée (par ex.application ['myDsn'] = "commandes"). Cela permet également de repérer plus facilement les écritures variables, qui sont un peu plus importantes que les lectures de variables. (Celui-ci est juste ma préférence)

Source: 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> 
Questions connexes