2012-04-30 6 views
2

非常に簡単なアプローチです。 2つのスレッド。 1は、ストレス下でのシステムの下でこれをログに記録しようとした場合InterlockedExchangeは、VMwareでは回避できません。

volatile __int32 p=0; 

1つのスレッド(A)は唯一

while(1){ 
    ExecuteAVeryCPUIntesiveThing(); 
    InterlockedExchange(&p, 0); 
} 

を使用する他のスレッド(B)は

while(1){ 
    if(0==InterlockedCompareExchange(&p,0,0)) 
     InterlockedExchange(&p, 1); 
} 

を使用しています。 Aからの値がpでB.

に伝播されません (メモリスワップ、IO、ソケット、CPUスパイク..の多くは)0 の価値を持っているように見える。しかしBの視点pから 私の世界でAが値を0に設定すると、Bは値を検出して0に設定しなければなりません。 これはまさにそのように動作しますが、esxiを実行しているときは動作しません。

これは実際のハードウェアの下でも、いくつかの仮想システムではうまく動作しますが、VMWareではうまく動作していないようです。

私は気になったことがありますか?

OSゲスト:win2008サーバー

のx64用のMicrosoft(R)C/C++最適化コンパイラバージョン15.00.30729.01でコンパイルさ

コード

ホスト:ESXi 4.1の

更新:

レスポンスコメントは:はいそれは0と1の間でバウンスしますが、 と書かれているように、スレッドBはバウンスしません。なぜなら、pの値は決してBのパースペクティブで変化しないからです。

非常に正確な時点でA(ExecuteAVeryCPUIntesiveThing();)でコードブロックを実行したいと思います。

生産コードはより多くのスレッドとイベント、mutexとロックでいっぱいですが、実際には残っていますが、上記のコードを使用して、私はゲストに多くのCPU、mm、ioを生成すると再現できますos。

+0

これはあまり意味がありません。あなたは何を達成しようとしています、もっと大きな仕事は何ですか? –

+0

これは実際のコードではありません(InterlockedExchangeCompareは存在しません)ので、実際に行っているかどうかはわかりません。あなたはどのような方法で失敗したかは言わなかった。コードは0と1を 'p'にバウンスさせるだけです。実際、 'if'ステートメントはそれを与えても意味がないようです。そして、while(1)?本当の問題は何ですか? –

+0

ここでは、インターロックを使用する理由は何ですか?なぜそれを使うのか、それは偽りのようだ。 MSVCの揮発性は、必要なすべてを提供します。 –

答えて

2

このコードは、起こるのを待っているスレッドレースです。仮想マシンには1つのプロセッサしか割り当てられていないため、おそらくVMWareから取得しているはずです。コードが欠落している何

は、スレッドBがpの変化の値を見を持っていることを保証インターロックです。したがって、スレッドAがCPUコアを取得してしばらく実行し続け、スレッドBがブロックされている場合、スレッドAはクォンタムが実行されるのを待ってから、pを0回以上0に設定できます。スレッドBは、それが決してpを1に戻す機会を得られなかったのでそれを知らないでしょう。

ロックデザインを再考する必要があります。この問題はVMWareだけに限定されず、通常のマシンでも間違っている可能性があります。 1ヶ月に1度、間違っています。与えるか、取るか、デバッグするのは不可能です。そうでなければ、これは古典的なプロデューサ/コンシューマのシナリオです。スレッドセーフなキューを使用して対処します。

+0

ああ、何かがあると思います。元のコードは、スレッドセーフなキューにmsg(Bから)をポストするだけでAのものをトリガーすることができましたが、私のストリップダウンの例ではこれらのすべてを削除しました。スレッドがすでにキューに入っていた場合、スレッドが1つの特別なメッセージをポストするのを防ぐためにロックが追加されました。 – Jonke

関連する問題