2016-09-21 9 views
0

フォローアップthis post。私の目標は、一度に1つだけのCalculateを持つことですので、私はSyncLockを追加しました:別スレッドにいなくても、SyncLockとMemoryBarrierを呼び出しても安全ですか?

Public Sub Calculate(Optional inBack As Boolean = True) 
    If Not inBack Then 
     InternalCalculate(-1, False) 
    Else 
     If CalcThread IsNot Nothing Then 
      CalcThread.Abort() ' yes, I will replace this 
      CalcThread = Nothing ' XXX 
     End If 
     If CalcThread Is Nothing Then 
      CalcThread = New Threading.Thread(AddressOf InternalCalculate) 
      CalcThread.IsBackground = True 
     End If 
     CalcThread.Start() 
    End If 
End Sub 

Private Sub InternalCalculate(Optional Line As Integer = -1, Optional isBack As Boolean = True) 
    Dim Lock As New Object 
    SyncLock Lock 
     Threading.Thread.MemoryBarrier() ' do this BEFORE a write, right? 
     isRunning = true 
     'do the expensive stuff 
    End SyncLock 
End Sub 

注意isBack。これが偽の場合、コードはmainで実行されるだけです。これは、単一のLineを再計算するときによく使用されます。だから私の質問は、これらの2つのラインの安全性についてです:

SyncLock Lock 
Threading.Thread.MemoryBarrier() 

それは私がメインで実行されているコードでこれらを呼び出す場合、何が起こるかthe documentationに私には明らかではありません。私はコードを追加しましたが、それは正常に実行されるようですが、私は自分がAbortのような別の問題に開かれていないことを確認したいと思います。これらはスレッド化と非スレッド化の両方で使用できますか?

+0

「スレッド」という用語は「実行のスレッド」の略で、すべてがスレッドなので、「シングルスレッドを使用しないプログラムの場合は「スレッド」となります。 'main'自体はスレッド内で実行されますが、単にスレッドのみであり、特別な作業はありません。すべてのプロセスにデフォルト/初期スレッドがあります。 – kfsone

+0

確かに、*同期*ロックは*同期スレッド用です。スレッドが1つしかない場合、*同期するものは何もありません。したがって、私の質問。 –

答えて

1

はい、シングルスレッドコードで使用するのは安全です。

InternalCalculateには、同時にコードを実行できる問題があります。 InternalCalculateを呼び出すたびに、新しいLockオブジェクトが作成されます。 Synclockは、同じオブジェクトを使用する場合にのみスレッドをブロックするので、Lockを読み取り専用メンバー変数にします。

複数のスレッドを実行すると、2番目、3番目、4番目などは、ロックを取得する最初のスレッドが同期ロックブロックを終了するまで待機します。その後、他の人は行くでしょう。したがって、これが一度だけ実行されるべきコードであれば、ダブルチェックロックパターンをチェックアウトする必要があります。

揮発性データの読み書きにMemoryBarriersを追加する代わりに、System.Threading.Thread.VolatileReadSystem.Threading.Thread.VolatileWriteを使用することをお勧めします。次に、読み書きを行う順序を覚えておく必要はありません。

+0

ありがとうございます@FloatingKiwi! Lock ASAPに変更を加える予定です。そのコードはMSの例から直接得られたものであり、私自身はその問題について興味を持っていました。宣言をSubの外に移動して囲みオブジェクトに移動するだけで十分ですか?本当に財産が必要ですか? –

+0

フォローアップ:isCalculatingブールの消費者はアプリ全体に広がっているので、VolatileReadを使用する必要があるのでしょうか?または、スレッド内にVolitileWriteを入れて、メインのコンシューマーがOKであることを確認してください。 –

+0

私の提案は読み取り専用フィールドであり、読み取り専用プロパティではありませんでした。これは、クラスのインスタンスごとに1つのロックオブジェクトを作成していることを明確にしています。揮発性コードに関しては、コードをまったく必要としないように再構成します。たとえば、あなたの結果を返す関数に計算を変更します。あなたが何を計算しているのか見ていなくても、どのようにあなたのオブジェクトと対話するのかは分かりません。 – FloatingKiwi

関連する問題