1

次のコードを使用して、リソースの使用を制限しています。

ときどき (正常に実行されてから 3 ~ 4 日後)、キューが空の例外が発生するか、返されたオブジェクトが null であることがわかります。

この Get メソッドに入るスレッドを 5 つだけに制限しているのでしょうか。

GetConnection が呼び出される場所では、ReleaseConnection も Final ブロッ​​ク内で確実に呼び出されます。

各呼び出しで、私もログインしていません。キュー内のリソースの。キュー カウントが 5 を超えることはないようです。

Semaphore smphSync = new Semaphore(0, 5);

Queue<IResource> resources;

private IResource GetResource()

{

    smphSync.WaitOne();

    IResource res = resources.Dequeue();

    return res;
}

private ReleaseResource(IResource res)

{

    resources.Enqueue(res);

    smphSync.Release();
}

私の質問は、lock/Monitor を使用して、キュー (リソース インスタンス) へのアクセスを同期する必要がありますか?

4

2 に答える 2

3

標準の .NET コレクションはどれも、既定ではスレッド セーフではありません。同時アクセスを防止するある種のメモリ バリアがなければ、それらに同時にアクセスすることはできません。

あなたの場合、セマフォは5つ以上のスレッドがアクセスするのを防ぎますが、これらの5つの同時スレッドのいずれresources同時に入ることを妨げるものは何もありませんDequeue()Enqueue()。これらのスレッド間でまれに競合状態が発生し、キューが破損する可能性は十分にあります。resourcesキュー自体をロックする必要があります。

を呼び出す前に、ロック内でテストを実行して、キューに削除するアイテムがまだあることを確認することもお勧めしますDequeue()。ただし、あなたのコードがどのように機能するかの詳細がわからないため、それが関連しているかどうかを判断するのはあなたに任せます.

Semaphore smphSync = new Semaphore(0, 5);
Queue<IResource> resources;
private _lockObj = new object();

private IResource GetResource()
{
    smphSync.WaitOne();
    lock( _lockObj ) 
    {
        IResource res = resources.Dequeue();
        return res;
    }
}

private ReleaseResource(IResource res)
{
    lock( _lockObj )
    {
        resources.Enqueue(res);
    }
    smphSync.Release();
}
于 2010-02-17T01:03:06.330 に答える
1

ThreadSafeQueueクラスに lock() を追加し、最近 TryDequeue() メソッドを追加しました。詳細については、この投稿を参照してください。以前に頻繁に見られた複数のスレッドの衝突が確実に改善されました (最も顕著なのは、キューに null が存在しない場合に null オブジェクトを返すことでした)。

編集: TryDequeue() メソッドをチェックインし、正しい変更セットへのリンクを更新しました。

于 2010-02-17T00:58:46.437 に答える