CFLOCK  
説明

共有データの整合性を維持します。次のロックを適用します。

Exclusive 本文内の CFML 構造に対してシングルスレッドのアクセスを行うことができます。このタグの本文は、一度に 1 つのリクエストでしか実行できません。あるリクエストが排他的ロックをかけている間は、タグ内のコードを他のリクエストが開始することはできません。ColdFusion は、排他的ロックを早い者勝ちで適用します。

Read-only 複数のリクエストがタグ本文内の CFML 構造に同時にアクセスできます。読み取り専用ロックは、共有データを読み取る場合にのみ使用し、共有データを修正する場合には使用しないでください。あるリクエストが共有データの排他的ロックを取得している場合、新規リクエストはその排他的ロックが解除されるのを待機することになります。

 
カテゴリ

アプリケーションフレームワークタグ

 
シンタックス
<cflock
   timeout = "timeout in seconds "
   scope = "Application"、"Server"、"Session"
   name = "lockname"
   throwOnTimeout = "yes"、"no"
   type = "readOnly"、"exclusive"> 
   <!--- 同期化する CFML ---> 
</cflock>
 
関連項目

cfapplication、cfassociate、cfmodule、『ColdFusion MX 開発ガイド』の第15章の「パーシスタントデータとロックの使用」

メモ: 共有データの構造体、ファイル、および CFX を更新するコードのスコープを制限してください。排他的ロックはこれらの更新の整合性を確保するために必要ですが、読み取り専用ロックの方が高速に処理されます。パフォーマンスを重視するアプリケーションの場合は、共有データを読み取るときなどは、できるかぎり排他的ロックではなく読み取り専用ロックを使用してください。
 
使用方法

ColdFusion MX はマルチスレッドサーバーです。したがって、一度に複数のページリクエストを処理することができます。cflock タグは、次の目的で使用します。

  • 同時に実行されるリクエストでの共有データやオブジェクトに対する修正が、整然とした順序で行われるようにします。
  • ファイル操作の構造をこのタグで囲み、ファイルの更新時に他のアプリケーションやタグがそのファイルを書き込み用に開いていることがないようにします。
  • CFX 呼び出しをこのタグで囲み、スレッドセーフな方法で実装されていない CFX を ColdFusion で安全に呼び出せるようにします (これは、C++ で開発された CFX にのみ該当します)。

ColdFusion を安全に動作させるには、共有 (グローバル) データ構造体の管理と操作を行う C++ CFX がスレッドセーフでなければなりません。しかし、これには高度な知識が必要です。CFML カスタムタグラッパーで CFX を囲むと、呼び出しをスレッドセーフにすることができます。

共有スコープで変数の表示、設定、更新を行う場合は、scope 属性を使用して Server、Application、Session のいずれかを特定してください。

 

デッドロックとは、ページ内のロックされた部分のコードをどのリクエストも実行できない状態です。デッドロックが発生すると、どのユーザーもロックを解除できなくなります。なぜなら、ロックタイムアウトによってデッドロックが解消されるまで、ページ内の保護されたセクションへのリクエストはすべて拒否されるからです。

cflock タグでは、カーネルレベルの同期オブジェクトを使用します。このオブジェクトは、それを使用しているスレッドがタイムアウトするか異常終了した時点で、自動的に解放されます。したがって、ColdFusion が cflock タグの処理中に永遠にデッドロックされることはありません。しかし、タイムアウト時間が長すぎると、リクエストスレッドが長時間にわたってブロックされ、スループットが急激に低下する可能性があります。これを避けるには、常に最低限のタイムアウト値を使用してください。

リクエストスレッドがブロックされる別の原因としては、cflock タグのネスト構造やロック名が一貫していないことが考えられます。ロックをネストする場合は、ロックされた変数にアクセスするコードが、一貫して同じ順序で cflock タグをネストする必要があります。そうしないと、デッドロックが発生する可能性があります。

次に、デッドロックが発生する例を示します。

ユーザーが 2 人の場合のデッドロックの例
ユーザー 1 ユーザー 2

Session スコープをロックします。

Application スコープをロックします。

デッドロック : Application スコープをロックしようとしますが、Application スコープはユーザー 2 によって既にロックされています。

デッドロック : Session スコープをロックしようとしますが、Session スコープはユーザー 1 によって既にロックされています。

読み取りロックの中に排他的ロックをネストしようとすると、次のようなデッドロックが発生する可能性があります。

ユーザーが 1 人の場合のデッドロックの例
ユーザー 1

Session スコープを読み取りロックでロックします。

Session スコープを排他的ロックでロックしようとします。

デッドロック : Session スコープは既に読み取りロックでロックされているので、Session スコープを排他的ロックでロックすることはできません。

次のコードは、この事例を示しています。

<cflock timeout = "60" scope = "SESSION" type = "readOnly">
   ...............
   <cflock timeout = "60" scope = "SESSION" type = "Exclusive">
   .........
   </cflock>
</cflock>

デッドロックを避けるには、ロックをネストするすべてのコードが、一貫した順序でネストし、一貫した名前を付ける必要があります。Server、Application、および Session スコープへのアクセスをロックする必要がある場合は、次の順序に従ってください。

  1. Session スコープをロックします。cflock タグ内で、scope = "session" を指定します。
  2. Application スコープをロックします。cflock タグ内で、scope = "Application" を指定します。
  3. Server スコープをロックします。cflock タグ内で、scope = "server" を指定します。
  4. Server スコープのロックを解除します。
  5. Application スコープのロックを解除します。
  6. Session スコープのロックを解除します。
メモ: スコープをロックする必要がない場合は、そのスコープのロックとロック解除の手順を省略できます。たとえば、Server スコープをロックする必要がない場合は、手順 3 と 4 を省略できます。名前付きロックにも同様のルールが適用されます。

詳細については、次のドキュメントや Web サイトを参照してください。

  • 『ColdFusion MX 開発ガイド』の第15章の「パーシスタントデータとロックの使用」
  • 弊社 Web サイト http://www.macromedia.com/support/service/ の記事 20370、「ColdFusion Locking Best Practices」
 
<!--- この例では、cflock を使用して Application、Server、および Session スコープ内の変数に対する
データ更新の一貫性を保つ方法を示します。 --->

<!--- 次のコードをアプリケーションのルートディレクトリの "Application.cfm" ファイルにコピーします。 --->
<!----------------   Application.cfm のコードの先頭   --------------->
<!--- cfapplication タグは、ColdFusion アプリケーションのスコープを定義し、
アプリケーション変数やセッション変数の保管を有効または無効にします。
このタグを、Application.cfm という特殊なファイルに挿入します。
このファイルは、同じディレクトリ内にある他のどの ColdFusion ページよりも先に実行されます。 --->

<!--- このアプリケーションのセッション管理を有効化します。 --->
<cfapplication name = "ETurtle"
   sessionTimeout = #CreateTimeSpan(0,0, 0, 60)# 
   sessionManagement = "yes">

<!--- E-Turtleneck で使用されるセッション変数とアプリケーション変数を初期化します。 
セッション変数にセッションスコープを使用します。 ---> 
<cflock scope = "Session"
   timeout = "30" type = "Exclusive">
   <cfif NOT IsDefined("session.size")>
      <cfset session.size = "">
   </cfif>
   <cfif NOT IsDefined("session.color")>
      <cfset session.color = "">
   </cfif>
</cflock>

<!--- タートルネックの販売数を記録する、アプリケーション全体を対象とする変数に
      対してアプリケーションロックを使用します。
      Application スコープを扱うためのより効率的な (ただし少々複雑な) 方法については、
      『ColdFusion MX 開発ガイド』を参照してください。--->
<cflock scope = "Application"       timeout = "30" type = "Exclusive">
   <cfif NOT IsDefined("application.number")>
      <cfset application.number = 0>
   </cfif>
</cflock>

<!----------------------- Application.cfm の末尾 ----------------------->    

<h3>cflock の例</h3>

<cfif IsDefined("form.submit")>
<!--- フォームが送信されているので、リクエストを処理します。 --->
   <cfoutput>
      E-Turtleneck をご利用いただき、ありがとうございます。ご注文いただいたタートルネックのサイズは 
<b>#form.size#</b>、
      色は <b>#form.color#</b> です。<br><br>
   </cfoutput>

<!--- セッション変数に値を代入するコードをロックします。 ----> 
   <cflock scope = "Session" timeout = "30" type = "Exclusive">
      <cfparam name = session.size Default = #form.size#>
      <cfparam name = session.color Default = #form.color#>
   </cflock>

<!---- Application スコープで販売されたタートルネックの数を更新する
      コードをロックします。 ---> 
   <cflock scope = "Application" timeout = "30" type = "Exclusive">
      <cfset application.number = application.number + 1>
   <cfoutput>
      これで、E-Turtleneck のタートルネック販売数は #application.number# 枚になりました。
   </cfoutput>
   </cflock>

<cfelse>
<!--- 送信されていない場合にのみフォームを表示します。 --->
   <cflock scope = "Application" timeout = "30" type = "Readonly">
      <cfoutput>
         E-Turtleneck は、これまでに、#application.number# 枚のタートルネックを販売しました。
      </cfoutput>
   </cflock>

   <form method="post" action="cflocktest.cfm">
      <p>おめでとうございます。世界で最も快適な着心地のタートルネックをお選びいただきました。
      ご希望の色とサイズをお選びください。</p>
      <table cellspacing = "2" cellpadding = "2" border = "0">
         <tr>
            <td>色をお選びください。</td>
            <td><select type = "Text" name = "color">
                  <option>レッド
                  <option>ホワイト
                  <option>ブルー
                  <option>ターコイズ
                  <option>ブラック
                  <option>オリーブグリーン
               </select>
            </td>
         </tr>
         <tr>
            <td>サイズをお選びください。</td>
            <td><select type = "Text" name = "size" >
                  <option>XX スモール
                  <option>X スモール
                  <option>スモール
                  <option>ミディアム
                  <option>ラージ
                  <option>X ラージ
               </select>
            </td>
         </tr>
         <tr>
            <td>選択したら [送信] を押してください。</td>
            <td><input type = "Submit" name = "submit" value = "送信"> </td>
         </tr>
      </table>
   </form>
</cfif>
TIMEOUT  
  必須
 

ロックを取得するときに待機する最大時間を秒単位で指定します。ロックが取得されると、タグの実行は継続します。ロックを取得できない場合の動作は、throwOnTimeout 属性の値によって異なります。timout="0" を指定した場合、タイムアウトは ColdFusion MX Administrator の [設定] ページでの "リクエストタイムアウト x" の設定 (この設定が有効なとき) により決まります。ただし、この設定が有効でない場合に timeout="0" を指定すると、ColdFusion はロックを取得するまで無限に待機することになります。

SCOPE  
  オプション
 

ロックのスコープです。name 属性とは排他の関係です。ロック名です。指定のスコープ内では、一度に 1 つのリクエストだけがこのタグ内のコード (または同じロックスコープの別の cflock タグ内のコード) を実行できます。

  • Application
  • Server
  • Session
NAME  
  オプション
 

ロック名です。scope 属性と併用することはできません。特定の名前を持つ cflock タグ内のコードを実行できるのは、一度に 1 つのリクエストだけに限られます。空の文字列は指定できません。

アプリケーションのさまざまな部分からのリソースへのアクセスを同期化できます。ロック名は、ColdFusion サーバーに対してグローバルです。ロック名は、アプリケーションおよびユーザーセッション間で共有できますが、クラスタ化された複数のサーバー間にわたって共有することはできません。

THROWONTIMEOUT  
  オプション
 
Default value: "yes"

タイムアウト条件を処理する方法です。

  • yes: タイムアウト時に例外が生成されます。
  • no: このタグの時間を経過しても実行が継続されます。
TYPE  
  オプション
 
Default value: "Exclusive"
  • readOnly: 複数のリクエストで共有データを読み取ることができます。
  • exclusive: 1 つのリクエストで共有データを読み書きできます。