1

以下のコードは、アプリケーションで使用するシングルトンを表しています。_MyObject = New Objectは、どのような状況でも複数回実行したくない、非常にコストのかかるデータベース呼び出しを表していると仮定しましょう。これが起こらないようにするために、最初に_MyObjectバッキング フィールドが null です。そうである場合は、SyncLock に割り込んで、一度に 1 つのスレッドだけがここに入ることができるようにします。ただし、シングルトンがインスタンス化される前に 2 つのスレッドが最初の null チェックを通過した場合、スレッド A がインスタンスを作成している間、スレッド B は SyncLock で待機することになります。スレッド A がロックを終了した後、スレッド B はロックに入り、インスタンスを再作成します。その結果、高価なデータベース呼び出しが行われます。これを防ぐために、ロック内で発生するバッキング フィールドの null チェックを追加しました。このようにして、スレッド B がロックで待機することに成功した場合、スレッド B は通過し、インスタンスを再作成しないことを確認するためにもう一度 null チェックを行います。

では、2 つの null チェックを行う必要は本当にあるのでしょうか? 外側の null チェックを取り除くことと、Synclock から始めることはまったく同じでしょうか? 言い換えれば、変数のスレッドロックは、複数のスレッドがバッキングフィールドに同時にアクセスできるようにするのと同じくらい高速ですか? その場合、外側の null チェックは不要です。

Private Shared synclocker As New Object
Private Shared _MyObject As Object = Nothing
Public Shared ReadOnly Property MyObject As Object
    Get
        If _MyObject Is Nothing Then 'superfluous null check?
            SyncLock synclocker
                If _MyObject Is Nothing Then _MyObject = New Object
            End SyncLock
        End If

        Return _MyObject
    End Get
End Property
4

2 に答える 2

2

これはおそらく、コメントではなく回答として優れているでしょう。

したがって、Lazy を使用して「作成されたインスタンスへの参照を返すよりも、高価な操作を 1 回だけ実行する」を実装します。

Private Shared _MyObject As Lazy(Of Object) = New Lazy(Of Object)(AddressOf InitYourObject)

Private Shared Function InitYourObject() As Object
    Return New Object()
End Function

Public Shared ReadOnly Property MyObject As Object
    Get
        Return _MyObject.Value
    End Get
End Property

これは、オンデマンドで 1 回限りの初期化を行う、非常に単純でスレッドセーフな方法です。このInitYourObjectメソッドは、必要な初期化をすべて処理し、作成されたクラスのインスタンスを返します。最初のリクエストでは、 を呼び出すと初期化メソッドが呼び出され_MyObject.Value、後続のリクエストは同じインスタンスを返します。

于 2014-06-30T14:28:56.310 に答える
1

If内部ステートメントを追加したことは絶対に正しいです(正しく指摘したように、それがなくても競合状態が発生します)。

また、純粋に論理的な観点から見ると、外側のチェックは不要であることも正しいです。ただし、外側の null チェックは、比較的高価なSyncLock操作を回避します。

考えてみてください: すでにシングルトンを作成していて、一度に 10 個のスレッドからプロパティをヒットした場合、アウターIfは、それらの 10 個のスレッドがキューに入れられて本質的に何もしないのを防ぎます。スレッドの同期は安価ではないため、追加Ifは機能よりもパフォーマンスのためです。

于 2014-06-30T11:14:11.163 に答える