ColdFusionでスコープロック(アプリケーション、サーバーなど)と名前付きロックをいつ使用する必要がありますか?

StackOverflow https://stackoverflow.com/questions/296721

質問

< cflock scope =" application">を使用するのが適切な場合または、< cflock name =" foo">とは対照的にilkです。

具体的には、CFLockを使用してアプリケーション、セッション、またはサーバースコープ内の共有オブジェクトを保護することに関心がありますが、ColdFusionでのロックのさまざまな使用方法についても知りたいです。

役に立ちましたか?

解決

アプリケーションスコープ内で変化する可能性のあるものを読み書きするときに使用する必要があります。例:

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

これをtype =&quot; exclusive&quot;でロックします。 application.myDataを使用する場合は常に、type =&quot; readonly&quot;が必要です。ロック。例外は、Application.cfcのOnApplicationStartメソッドで、それ自体をロックします。同様に、セッションとサーバーのスコープで同じ戦略を使用します。

名前付きロックを使用すると、ロック戦略をより詳細に制御できます。コマンドを動的にロックする必要がある場合は、名前付きcflockを使用します。例:

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

この例では、異なるタイプのユーザーは同時にファイルを書き込むことができますが、同じ session.user_type を持つユーザーはお互いを待つ必要があります。このcflockは、ファイルの競合の問題を回避するのに役立ちます。

名前付きロックを使用するもう1つの理由は、現在の操作の範囲がわからない場合です。インスタンス化されたcfcにいる場合、どのスコープにインスタンス化されたかをどのようにして知るのですか?変数?セッション?応用?優れたカプセル化により、オブジェクトは伝えられたこと以外は何も知らないことがわかります。 CFC内で、名前付きロックを使用して、CFCにちなんで名前を付けるか、ユースケースに応じてCFCと一意のインスタンス変数に名前を付けます。

他のヒント

@Mr。ネイトは、競合状態が心配なときはいつでもロックを使用します。たとえば、セッションの初期化をロックしたいが、その後の読み取りはロックしない場合があります。同様に、読み取りではなく、アプリケーションスコープへの書き込みをロックすることもできます。

読み取りをロックすることは、スレッドセーフなシェア変数スコープを導入したCF6以降、あまり役に立ちません。悪い昔、注意を怠ると、同じメモリアドレスを同時に読み書きすることができました。ただし、CFはJavaで動作するようになったため、これは問題ではありません。

名前付きロックは、彼が示したように、ファイルの読み取り/書き込みなど、スコープ外のすべてをロックするのに役立ちます。

他の提案をここに構築します。

正直に言うと、cf8の登場により、duplicate()がオブジェクトを複製できるようになったため、アプリケーション、セッション、またはサーバースコープへの書き込み時にのみスコープロックを使用します(ところで、サーバースコープへの書き込みは、私の本ではありません)。

データを読み出す必要がある場合、私はduplicate()を使用してローカル変数にデータのディープコピーを行い、読み取りロックをすべて回避します。これにより、デッドロックが防止されます。

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

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

名前付きロックを使用する絶好のタイミングは、「トランザクション」がある場合です。たとえば、データベース内の複数のテーブルを一度に更新する場合、または2人のユーザーが同じデータベースレコードを一度に更新しないようにする場合、または読み取りまたは一度に複数のユーザーがアクセスしようとするサーバー上のファイルに書き込みます。

簡単に言えば、2つの要求が同時に同じことを行おうとして問題が発生する可能性がある状況があるときはいつでも、名前付きロックをその周りに配置します(または、セッション、アプリケーション、またはサーバースコープに厳密に関係する場合) 、その後、スコープロックを使用します)。

Ben Nadelがブログエントリに投稿したことがあります:

  

&quot;私が見ているように、2つの条件が満たされていないと、   CFLockの使用:

     
      
  1. 共有リソースがアクセスまたは更新されています。
  2.   
  3. 負の結果をもたらす競合状態の可能性がなければなりません。&quot;
  4.   

トランザクションの周りの名前付きロック、内部にネストされたセッションまたはアプリケーションスコープのロックなど、CFLOCKタグをネストすることもできますが、慎重に行います。要求がページのロックされたセクションを実行できず、ページのロックされたセクションへのすべての要求がタイムアウトになるまでブロックされる場合があります。 (ColdFusionマニュアルには、ネストされたロックのベストプラクティスが記載されています。)

通常、競合状態を防ぐために、Application.cfcの外部でこれらの変数を読み取りまたは変更するときは、常にセッション、アプリケーション、およびサーバー変数にcflockを使用する必要があります。参考になる記事を次に示します。

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

編集:スコープに関する質問にさらに回答するために、共有リソースとやり取りするときは常に&lt; cflock scope =&quot; application&quot;&gt; を使用します。

これは、ページ変数を使用して「ローカルフラグ」を作成するColdFusion 8ドキュメントの例です。ロックせずに読み取って、アプリケーション変数が初期化されているかどうかを確認できます。

これが解決するのは、ページがロードされるたびに排他ロックを実行すると、ロックにより多くの処理時間がかかるためボトルネックが発生する可能性があるため、排他ロックを条件付けする必要があるという事実です。

より良いテクニックが登場したかどうかはわかりませんが、とにかくここに投稿するつもりです。 ColdFusionのドキュメントでは多くの場合、適切なコードが提供されていないため、このコードを改善する方法を誰かが確認できるかどうか興味があります。

  • ローカルフラグをリクエストスコープに入れて、カスタムタグなどでも使用できるようにすることができます。ただし、実際にはapp.cfmでのみ必要なので、おそらく不要です。
  • また、すべてのスコープを循環する必要がないように、structKeyExists()を優先してisDefined()を削除します。
  • また、大文字と小文字が保持されるように、変数を設定するために括弧表記を使用します(例:application ['myDsn'] =&quot; orders&quot;)。また、変数の読み取りよりも重要な変数の書き込みを見つけやすくなります。 (これは私の好みです)

出典: 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>
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top