2010-11-30 14 views
6

数ヶ月前に私は現在の会社内で仕事をしていましたが、強力なウェブ開発の背景はありませんでしたが、彼が私に提出した質問の1つは、このコードブロックを改善してください。ウェブアプリケーションで「ロック」を使用する

私はコードブロックを完全に覚えていませんが、それを集計するのはウェブのヒットカウンターで、彼はヒットカウンターでロックを使用しました。

lock(HitCounter) 
{ 
    // Bla... 
} 

しかし、いくつかの議論の後、彼は言った、ロックは良いですが、Webアプリケーションで使用することはありません!

彼の声明の背景には何がありますか?なぜ私はWebアプリケーションでロックを使用しないでください?

+5

Webアプリケーション特に並行性が高いことが必要な場合を除いて、特に特別なものではありません。アプリケーションのタイプにかかわらず、必要であればいつでも 'lock'を使用してください。 – LukeH

+0

HitCounterはクラスまたはインスタンスですか? –

答えて

6

ウェブアプリケーションでロックを使用しないようにする特別な理由はありません。ただし、ロックブロックが競合した場合にブロックを引き起こす可能性のあるマルチスレッドアクセスをシリアル化するメカニズムであるため、注意深く使用する必要があります。しかし、これはWebアプリケーションの懸念ではありません。

現代のハードウェアでは、常に覚えておく価値があるのはan uncontended lock takes 20 nanoseconds to flipです。これを念頭に置いて、ロックブロックの内部にコードをできるだけ最小限にしようとする通常の習慣に従わなければなりません。ブロック内に最小限のコードがある場合、オーバーヘッドは非常に小さく、競合が少ない可能性があります。

ロックはと決して言わないと、は本当に毛布の声明です。それは実際にあなたの要件が何であるかに大きく依存します。要求間で共有されるスレッドセーフなメモリ内キャッシュは、データベースからのオンデマンドフェッチよりも要求のブロックが少なくなる可能性があります。

最後に、BCLとASP.Net Frameworkタイプは確かに内部的にロックを使用するため、間接的にそれらを使用しています。

6

アプリケーションドメインがリサイクルされている可能性があります。

これにより、古いappdomainは依然としていくつかのリクエストを処理し終え、新しいappdomainは新しいリクエストを処理することになります。

静的変数はそれらの間で共有されないため、静的グローバルでのロックはこの場合排他性を与えません。

0

このコードは、すべての着信要求が前のロックが解除されるまでこの時点で待機する必要があるため、アプリケーションのボトルネックとなります。

+1

まだ、これはウェブアプリケーションに固有のものではありませんか? – xtofl

+0

@xtofl - これはWebアプリケーションに固有のものではありませんが、このページは、すべてのユーザーがアクセスするWebアプリケーション内のポイントです。他のアプリのロックは、控えめに使用することができ、影響の少ないエリアで使用できます。 –

+1

着信要求を処理するために別々のスレッドを使用するアプリケーションと、すべてのスレッドがこのコードを通過するアプリケーションに固有です。 Webアプリケーションはそのような良い例です。それは...ですか ? – VdesmedT

2

まず、実際にどのアプリケーションでも使用するオブジェクトをロックすることは決してありません。あなたがウェブのために数百または数千かもしれないオブジェクトにアクセスしようとするすべてのスレッドを(ブロックロック時に、質問のウェブ部分については

private readonly object _hitCounterLock = new object(); 
lock(_hitCounterLock) 
{ 
    //blah 
} 

を:あなたはロックオブジェクトを作成し、それをロックしたいですのユーザー)。彼らはすべてのスレッドがロックを解除するまで待っています。

+0

第2に、読み取り専用ではない参照をロックしないでください。 –

+0

真実:-)私に思い出させていただきありがとうございます。今更新しています。 –

0

ロックは、複数のスレッドが同じ共有変数へのアクセスを必要とするマルチスレッドアプリケーションでのみ使用されるため、ロックは要求スレッドによって排他的に取得され、保留中のすべてのスレッドはロックを解除してロックが解除されるまで待機します。データベースの読み取り/書き込み操作をロックしようとしている場合は、デフォルトで

+0

Webアプリケーションは、複数のリクエストを同時に処理できるマルチスレッドアプリです。 – VdesmedT

+0

はあなたがポイントを拾っていないように見えます。私はリクエストが互いに分離されている、というのは、通常の場合、共有またはアプリケーションのスコープ変数を使用しない限り、ロックが必要ないということです。 –

+0

ええ、私は人々がそのコンセプトに問題を抱えている理由を知らない。人々は、「ウェブアプリケーション上のロックを使用しない」とは、「ウェブアプリケーション上のロックは悪い」ことを意味すると思われる。ポイントは、あなたがロックを使用して始めるのは決して決して決してできないということです。私の同様の答えが投票されました。 –

0

カップルの理由...

  1. をロックする必要がないので、Webアプリケーションで

    は、ユーザーの要求が隔離されていますとにかく、データベースがロックを行っているプロセスによって所有されていないため、他のプロセスによって読み書きされる可能性があるため、競合状態が発生するリスクは非常に高くなります。アプリケーションごとに複数のプロセス。

  2. ロックは通常、非UIスレッド(バックグラウンド/ワーカースレッド)のクライアントアプリケーションで使用されます。複数のコアを利用しようとしている場合(リクエストに関連するオブジェクトに対するロックが受け入れられる場合)以外は、Webアプリケーションはマルチスレッド処理にはあまり使用されません。とにかく出力全体(または少なくとも一連のchunk)が処理されるまで、サーバーは応答できません。

+0

ポイント1は、Webアプリケーションだけでなく、どのアプリケーションドメインにも適用できます。ここではトランザクションを使用します。 –

+0

ポイント2ロックはドメイン固有ではないため、「標準的な」アプリケーションタイプの使用はありません。 –

+0

1.あなたはポイントを逃しています。データベースは通常、別々のプロセスで動作します。トランザクションを使用することはできますが、ロックを使用しないもう1つの理由です。あなたはここでもポイントを逃しています。デスクトップアプリケーションでは、クライアントスレッドが応答する必要があるため、大量の操作は非同期で行われます。これは、IOとCPUが別々に動作できる状況にある場合を除いて、Webアプリケーションではそうではありません。その場合は、とにかくロックを使用しないことになります。少なくとも、直接ではありません。 –

2

後期:)が、これを将来の読者のために、追加のポイント:

アプリケーションがWebファーム上で実行されている場合は、複数のマシン上のASPの実行中は、だから、ロックオブジェクト

を共有することはありませんが 1.ウェブファームはサポートされていなくてもかまいません2. ASPが設定されていて(既定値ではない)、古いリクエストが提供されるまでリサイクル中に並列インスタンスを使用しないでください(上記のAndrasの説明のとおり)

関連する問題