2011-01-14 3 views
0

にロックを同期するために、私はそれに2つのメソッドを持つクラスを持って、1スレッドの数を作成し、実行クラスを呼び出して、他はそれらのスレッド上げイベントを処理するイベントハンドラです完了してから(最初のメソッドを再度呼び出します)。どこで、どのようにこのコード

私がイベントを処理するメソッドは、イベントを発生させたスレッドで実行されることを理解しています。だから、のような、私はどのように多くのスレッドが実行されていると言うメンバ変数をSyncLockし、それから1を引く:

SyncLock Me //GetType(me) 
    _availableThreads -= 1 
End SyncLock 

だから私はいくつか質問があります。

主な質問:は私がSyncLockれるべき」をクラスでどこでも_availableThreadsをINGの - (スレッドが作成されたときに1を加算する)この質問に関連

サイドの質問スレッドを作成する方法、すなわち:

  1. が、私は通常、現在のインスタンスをSyncLockと思いますが、私は代わりにタイプをSyncLocksコードを見てきましたので、Me(現在のインスタンス)をロック同期とGetType(me)の違いは何ですか?

  2. は2間のパフォーマンスの違いがあるでしょうか?それ以外のものには影響を与えない、おそらくクラス内のものをロックする目的のために作成された別の「南京錠」オブジェクトのような、上記のためにロックできる小さなものがありますか?

注:_availableスレッドの唯一の目的は、任意の時点で実行すると、スレッドの実行に時間がかかることがジョブを処理することができますどのように多くのスレッドを制御することです。

コード:

Public Class QManager 
    Private _maxThreadCount, _availableThreads As Integer 

    Public Sub New(ByVal maxThreadCount As Integer) 
     Me.MaximumThreadCount = maxThreadCount 
    End Sub 

    Public Sub WorkThroughQueue() 

     //get jobs from queue (priorities change, so call this every time) 
     Dim jobQ As Queue(Of QdJobInfo) = QueueDAO.GetJobList 


     //loop job queue while there are jobs and we have threads available 
     While jobQ.Count > 0 And _availableThreads <= _maxThreadCount 

      //create threads for each queued job 
      Dim queuedJob As New QdJob(jobQ.Dequeue) 
      AddHandler queuedJob.ThreadComplete, AddressOf QueuedJob_ThreadCompleted 

      _availableThreads += 1 //use a thread up (do we need a sync lock here?)*************************** 
      queuedJob.Process() //go process the job 

     End While 

     //when we get here, don't do anything else - when a job completes it will call this method again 
    End Sub 

    Private Sub QueuedJob_ThreadCompleted(ByVal sender As QdJobInfo, ByVal args As EventArgs) 

     SyncLock Me //GetType(me) 
      _availableThreads -= 1 
     End SyncLock 

     //regardless of how the job ended, we want to carry on going through the rest of the jobs 
     WorkThroughQueue() 

    End Sub 



#Region "Properties" 


    Public Property MaximumThreadCount() As Integer 
     Get 
      Return _maxThreadCount 
     End Get 
     Set(ByVal value As Integer) 
      If value > Environment.ProcessorCount * 2 Then 
       _maxThreadCount = value 
      Else 
       value = Environment.ProcessorCount 
      End If 
      LogFacade.LogInfo(_logger, "Maximum Thread Count set to " & _maxThreadCount) 

     End Set 
    End Property 

#End Region 

End Class 

答えて

2

残念ながら、ここではいくつかのことを行う必要があります。

まず第一に、私はSyncLockを避け、および変更_availableThreadsを処理するためにInterlocked.IncrementとInterlocked.Decrementを使用してお勧めします。これにより、ロックなしでその変数にスレッドの安全性が提供されます。

つまり、複数のスレッドから使​​用されている場合は、キューへのアクセスのたびにSyncLockが必要になります。別の方法として、.NET 4を使用している場合は、Queueの代わりに新しいConcurrentQueue(Of T)クラスを使用するように変更することもできます。 SyncLockを使用する場合は、クラスによってのみアクセス可能なプライベートオブジェクトを作成し、すべての同期に使用する必要があります。

+0

非常に興味深い...私は連動クラスを認識していませんでした。ありがとう。 –

+0

キューについての良い点 - 私は3.5を使用していますので、残念ながらそれは不可能です。スレッドに再結合して最初のメソッドを呼び出すことは可能ですか?あなたはこれを行う方法を知っていますか?おそらくthread.joinを使用していますか? –

+1

@ Mr Shoubs:いいえ、実際はありません。 3.5を使用している場合は、キューへのすべてのアクセス(EnqueueとDequeueの両方)のために、プライベートオブジェクトのSyncLockを使用することをお勧めします。 –

6

あなたがすべきではないSyncLockインスタンスまたはタイプ。完全にクラスの制御の範囲内にある変数に対しては常にSyncLockが必要で、どちらもそうではありません。プライベートNew Objectを宣言し、SyncLockに使用する必要があります。

Private lockObject as New Object() 

...あなたは数を減少させるために、ここにデクリメント()メソッドをインタロッククラスを使用する必要があります

SyncLock lockObject 
    ... 
End SyncLock 
2

。はい、どこでも変数にアクセスします。 SyncLockミーを使用

はSyncLockメソッドGetType(ME)と同様に悪いです。誰かが誤ってデッドロックを起こすことがないように、常にプライベートオブジェクトを使用してロックする必要があります。ゴールデンルールは、データをロックすることができないということです。データにアクセスするコードだけをブロックすることができます。コードはあなたのプライベートな実装の詳細なので、ロック状態を保持するオブジェクトもプライベートなディテールでなければなりません。あなたのオブジェクト(私)もそのオブジェクトのタイプもプライベートではありません。他のコードが偶然それをロックすることを許可します。

1

スレッドカウンターをセマフォーに置き換えることができます。 Semaphoreを使用する場合、whileループを終了する必要はなく、どちらもThreadCompletedイベントハンドラからWorkThroughQueue()を呼び出す必要はありません。セマフォはスレッドセーフなので、ロックせずに使用できます。

http://www.albahari.com/threading/part2.aspx#_Semaphore

+0

これは良い情報です、ありがとう!私は、スレッドにも参加することを学びたいので、私が使用しているメソッドとセマフォの両方を調べます。 –

関連する問題