CFCをアプリケーションスコープに格納することに関する多くの投稿を読みましたが、CFCがデータを格納する場合、そのデータをアプリケーションスコープに含めるべきではないことを理解しています。実用的でないものを実行するすべてのCFCは、ユーザー名や電子メールアドレスなどのパラメーターを渡すとデータを保存するため、実用的でないcfcのアプリケーションスコープを使用するタイミングと使用しないタイミングがわかりません。
私の質問はposthandler.cfc
、ユーザーからの投稿を処理する約500行のコードのコンポーネントがあることです(SOがこのサイトに投稿された各質問を処理するのと同じように)。posthandler.cfc
コンポーネント:
返されたURLは、ユーザーをURLにリダイレクトする単純なJqueryajax呼び出しによって受信されます。
これはサイトで非常に定期的に発生し、現在、投稿ごとに新しいCFCインスタンスが作成されています。代わりにアプリケーションスコープに入れて、レース/ロック状態を引き起こさないのは安全ですか?
パラメータを渡すだけでは、何も「保存」されません。概念的に、各スレッドはそれ自身の持つarguments
とlocal
他のスレッドには見えないである、スコープを、そして場合関数が終了存在しなくなります。したがって、その観点からは、競合はありません。
また、データを保存することは、データをデータベーステーブルに保存することを意味するものではありません。共有スコープ/オブジェクトなどにデータを格納することで状態を維持するコンポーネントを指します。「共有」とは、リソースが他のスレッドからアクセス可能であることを意味し、複数のスレッドによって同時に変更される可能性があり、競合状態につながる可能性があります。 。
たとえば、variables
スコープ内の情報を「保存」するこの(考案された)コンポーネント関数を考えてみましょう。そのコンポーネントの新しいインスタンスを毎回作成する場合、各リクエストは独自のインスタンスと、操作するvariables
スコープの個別のコピーを取得するため、関数は安全です。
public numeric function doStuff( numeric num1, numeric num2 ) {
variables.firstNum = arguments.num1 * 12;
variables.secondNum = arguments.num2 * 10;
return variables.firstNum / variables.secondNum;
}
次に、同じコンポーネントを取得して、アプリケーションスコープに配置します。それはもはや安全ではありません。application
スコープに格納するとすぐに、インスタンス(およびそのインスタンス)variables
もアプリケーションスコープになります。したがって、関数がデータをvariables
スコープに「保存」すると、基本的にapplication
変数が更新されます。明らかに、これらはすべてのリクエストにアクセスできるため、スレッドセーフではありません。そのため、複数のスレッドが同じ変数を同時に簡単に読み取ったり変更したりして、競合状態を引き起こす可能性があります。
// "Essentially" becomes this ....
public numeric function doStuff( numeric num1, numeric num2 ) {
application.firstNum = arguments.num1 * 12;
application.secondNum = arguments.num2 * 10;
return application.firstNum / application.secondNum;
}
また、James A Mohlerが指摘したように、スコープを省略した場合にも同じ問題が発生します。スコープなしで関数変数を宣言しても、関数に対してローカルにはなりません。これにより、デフォルトのスコープの一部になります:-(variables
上記と同じスレッドセーフの問題が発生します)。開発者が単一のクエリ変数またはループインデックスのスコープを忘れると、この動作により多くのスレッドバグが発生します。したがって、必ずすべての関数変数を明示的にスコープしてください。
// Implicitly creates "variables.firstNum" and "variables.secondNum"
public numeric function doStuff( numeric num1, numeric num2 ) {
firstNum = arguments.num1 * 12;
secondNum = arguments.num2 * 10;
return firstNum / secondNum;
}
ロックを追加する以外に、代わりにスコープを明示的に使用することで、両方の例をスレッドセーフにすることができますlocal
。一時的なlocal
スコープにデータを格納することにより、データは他のスレッドからは見えなくなり、関数が終了すると存在しなくなります。
public numeric function doStuff( numeric num1, numeric num2 ) {
local.firstNum = arguments.num1 * 12;
local.secondNum = arguments.num2 * 10;
return local.firstNum / local.secondNum;
}
明らかに、参照によって渡される複雑なオブジェクトや構造、およびそれらのオブジェクトが関数内で変更されるかどうかなど、考慮すべき他のケースがあります。しかし、うまくいけば、その小屋「セーブデータ」とどのようにスコープが状態の違いによって作ることができるもので何にいくつかの光以下の成分(のための安全application
スコープ)と状態FUL部品(ありません)。
TL; DR;
あなたの場合、ほとんどの情報は共有されておらず、リクエストレベル(ユーザー情報、アップロードされた画像など)であるように思われるため、アプリケーションスコープに保存するのはおそらく安全です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加