2011-01-14 4 views
3

次のようなコードでは、Proc1とProc2が異なるプロセッサで同時に実行される場合、ThingVal2が5以外の値(たとえばゼロ)を取得することは可能ですか?フィールドを参照解除するときにメモリバリアが必要(.net x86またはx64)ですか?

 
Class SimpleThing 
    Public X As Integer 
    Sub New(ByVal value As Integer) 
     X = value 
    End Sub 
End Class 
Class ConcurrencyTest 
    Dim Thing1 As New SimpleThing(5) 
    Dim Thing2 As New SimpleThing(0) 
    Dim ThingRef As SimpleThing = Thing1 
    Dim ThingVal1, ThingVal2 As Integer 
    Sub Proc1() 
     Thing2.X = 5 
     Threading.Thread.MemoryBarrier() 
     ThingRef = Thing2 
    End Sub 
    Sub Proc2() 
     ThingVal1 = Thing2.X 
     ThingVal2 = ThingRef.X 
    End Sub 
End Class 

私は、IA64のような弱いモデルでは、はProc2が変わったとThingRef見るが、そうしたとしてThing2のフィールドXが表示されない可能性が現実の可能性があることを知っています。 x86またはx64上で実行されている.Netアプリケーションの場合、そのリスクは存在しますか? Proc1がSimpleThingの新しいインスタンスを作成し、そのXフィールドを5に設定し、ThingRefを指すように設定すると、危険を回避するのに十分であるか、新しいものがキャッシュラインに割り当てられる可能性があります。 Proc2スレッドがアクセスした何か他のものと共有されましたか?

マルチスレッドコードの一般的なパラダイムは、不変オブジェクトを作成し、それを指すように(おそらくInterlocked.CompareExchangeを使用して)変更可能な参照を設定することです。スレッド化に関係なく不変型を読むことはx86/x64上では常に安全ですか、それとも問題を引き起こす可能性がありますか?後者の場合、信頼できる動作を保証するためにvb.netでどのような方法が好まれますか?

また、このような問題が発生しないような方法でコードを実行する必要があることを指定する方法はありますか(たとえば、IA64のように正しい動作を保証できない単一のコアに実行を制限するなど)

+0

不変は、その値を1サイクルで読み取ることができる場合にのみ保証されます。 Intとboolはそのカテゴリに分類されます。長い間、そして確かに文字列ではないことは確かではありません。 – SRM

+0

@SRM:不変オブジェクトは、他の誰かが参照を利用できるようになると決して変更されないオブジェクトです。上記の「SimpleThing」オブジェクトは、.net x86および.net x64メモリモデルで保証されているかどうかを正確に確認しようとしているため、不変ではありません。 – supercat

答えて

0

よろしくお願いします。私が知っていることに答えようとします。

-1。あなたのコード例:

CLR 2.0以降は店舗を注文しています。つまり、ThingValはx86/x64では常に5になります。確かに。私は本当のIA64で試してみませんでしたが、IA64でもうまくいくはずです。なぜなら、CLRはすべてのプラットフォームで順序付けされた書き込みを確実に行うべきであり、単純な例で十分であるはずです。

-2。 IA64とx86/x64:

x86/x64のメモリセマンティクスは異なり、IA64のようなリスクはありません。ここで唯一起こり得る問題は、実際にはより高いレベルの言語を使用していることです。コンパイラが最適化コンパイラを使用している場合(C++のように)、コンパイラの最適化方法を正確に知らなくても予測できません。説明されていない:VBはグローバル最適化などを実行しないので、コードは安全です。

-3。 ad不変:

あなたが本当にそれを読んで本当に不変であれば、それは安全です。

-4。広告のシングルコア:

スレッドアフィニティを設定できます。各スレッドの標準プロパティであり、スレッドが実行できるCPUを定義します。 (.netのスレッド親和性設定は、オペレーティングシステムの親和性を直接変更します。)しかし、あなたのプログラムはゆっくり実行されます。

また、C#に切り替えてvolatileというキーワードを使用することもできます。これは、すべてのCPUで直ちに表示される揮発性変数に変更を加え、ここで示したすべての可能な問題を解決するため、より簡単に生きるのに役立ちます。残念ながら、VBはこのキーワードを提供しません。

+0

私はx86が店舗を発注したことは知っていますが、ここでの問題は負荷の依存関係にあります。インスタンス2のフィールドXは、Instance2.XまたはThingRefが書き込まれる前にProc2で読み取られている可能性があります。 .NETでは、コードがThingRef.Xを読み込んだときに、単にInstance2.Xの読み込みからキャッシュされた値を使用しないという保証はありますか?それは議論されていないコーナーケースです。 – supercat

+0

私は、いくつかのスレッドが実行されることだけが指定されていることを知っています。コア#5、しかし、それは過剰に見える。実際には、2つ以上のスレッドを異なるプロセッサ上で同時に実行しないように指定し、あるプロセッサから別のプロセッサに実行が移行するたびに、古いプロセッサと新しいプロセッサがキャッシュをその順序でフラッシュする必要があります。 – supercat

+0

はい、「順序付きストア」は、ThingRef.Xを読むときに、新しいThingRefと新しいX、または古いThingRefと古いXの両方を読み取ることを保証します。これはXがThingRefの内部にあるためです。それは安全です。あなたが同じ物の中にX1とX2を持っていて、互いに関連していたならば、注文された店であっても安全ではないかもしれません。 –

関連する問題