2009-11-02 7 views
5

キューにキューがあるモジュールがあるとします。.NET - Queue.Enqueueメソッドは安全ですか?

エンキューに他のエンティティのために、彼らは機能を経由しなければならない:私は複数のスレッドが動作している場合は

public sub InsertIntoQueue(Obj) 
    MyQueue.Enqueue(Obj) 
end sub 

を、彼らはInsertIntoQueue()を呼び出したい、この見なさスレッドは安全なのですか?

InsertIntoQueue()関数を実行するために必要なメモリ内に命令のコピーが1つしかないと思っていますが、スレッドセーフであると思うようになります。

しかし、2つのスレッドが同時にこの関数を実行しようとするとどうなりますか?

このスレッドは安全ですか?そうでない場合は、どうすればスレッドセーフにすることができますか? (速度とメモリ使用に関するパフォーマンスの影響は何か)

答えて

8

使用Queue.Synchronizedラッパーとしてあなたの方法を変更するオブジェクトを追加することを示唆しています。

4

これはスレッドセーフではありません。

このタイプのパブリックstatic(Visual BasicではShared)のメンバーは、マルチスレッド操作で安全です。インスタンスメンバーはスレッドセーフであることは保証されていません。

MSDN Siteより。

私はあなたのオブジェクトに

Dim SyncHandle as Object = new Object() 

を同期ハンドルを表しており、このような

Public Sub InsertIntoQueue(Object item) 
    SyncLock SyncHandle 
     MyQueue.Enqueue(item) 
    End SyncLock 
End Sub 
1

命令セットが1つでもスレッドセーフであるとは限りません。限り、指示が行く限り、常に1つのセットがあります。

ここで、提供したコードサンプルを見ると、スレッドセーフであるかどうかを判断することは不可能です。 Queueを含むすべての標準.NETコレクションはスレッドセーフではありませんが、同期されたバージョンのthmeselvesにアクセスできます。

パフォーマンスのトレムには、もちろん、パフォーマンスのヒットもあります。これは、ロックの範囲やその他のものによって異なります。特に、Webアプリケーションでのグローバルロックを使用すると、高負荷の下で深刻なボトルネックになることができ

2

OPのオフトピック少し行くのリスクが

SyncLock MyQueue 
    MyQueue.Enqueue(Obj) 
End SyncLock 

End Subの

0

を行い、考察を与えられるべきですキューの他のメソッドに渡します。私はオブジェクトをデキューする少なくとも1つのスレッドがあると仮定し、キューが空であるかどうかを確認することもできます。

複数のスレッドがデキューしていて、デキューを呼び出す前にキューが空でないかどうかをチェックして(無効な操作の例外を防ぐために)デキューの観点から見ると、あるスレッド(スレッドa)キューの最後の項目をデキューできます。もう1つのスレッド(スレッドb)は、キューが空ではなく、デキューを呼び出しているため、スレッドaは無効な操作例外を引き起こします。

ロックをチェックの周りに置いて空にし、デキューでこれを回避することができます。

Thisthisは、スレッドの安全性についての興味深い記事であり、また私は、彼らがすべてのvb.netではない一方で、彼らは詳細に説明スレッド、thisおよび/またはthisを読んでお勧めすることができます。

+0

私の計画は、複数のスレッドをエンキューすることと、キュー全体を特定の間隔でロックしてフラッシングする単一のスレッドです。 –

+0

キュー内のすべてのオブジェクトを処理している間にロックすると、エンキューしているすべてのスレッドはデキュースレッドが終了するまでブロックされます(エンキューしようとするとブロックされます)。それぞれの空のチェックとデキューをロックする方がよい場合がありますキュー全体の処理ではなくオブジェクトを使用します。 – Matt

0

私はスレッドの安全性に関する専門家ではありませんが、私はそのことについてできる限り学びたいと思っています。

私は、あなたと同じように、この操作はスレッドセーフであり、別のスレッドのキューデータに書き込むだけで、デキューは行われていないと思っていました。しかし、誰かがここで説明する(およびMSDNのドキュメントでどこにでもある)として:(Visual BasicではShared)

この型のpublic static メンバーは 、マルチスレッド操作で安全に使用できます。インスタンス のメンバーは、スレッドセーフで であることが保証されていません。多分内部MyQueue.Enqueue(Obj)はこのように行われていることを意味

  1. キューに置くデータ();
  2. 拡張キューポインタ。

このようにすれば、スレッドが2つのスレッドで同じ位置を上書きすることができるため、スレッドの問題が発生します。すでにポインタをインクリメントすることができました。

ここで述べるように、Queue.Synchronized()を使用してEnqueue()メソッドをロックするか、パフォーマンスに大きな影響を与えるが、キューにアクセスするときにプライベートプロパティをロックするこのようにオブジェクト(あなたがキューで行うものはスレッドセーフではないことになるので):

Private ReadOnly Property MyQueue() as Queue 
Get 
    SyncLock (m_myQueueLock) 
     Return m_myQueue 
    EndSyncLock 
End Get 
End Property 

は、この情報がお役に立てば幸い!

関連する問題