競合状態を引き起こす単体テストを書かなければならないので、後で問題を修正したかどうかをテストすることができます。 問題は、競合状態が非常にまれにしか発生しないことです。おそらく、コンピュータに2つのコアしかないためです。Javaで競合状態を呼び起こす
class MyDateTime {
String getColonTime() {
// datetime is some kind of lazy caching variable declared somewhere(does not matter)
if (datetime == null) {
initDateTime(); //Uses lazy to initlialize variable, takes some time
}
// Colon time stores hh:mm as string
if (datetime.colonTime == null) {
StringBuilder sb = new StringBuilder();
//Now do some steps to build the hh:mm string
//...
//set colon time
datetime.colonTime = sb.toString();
}
return datetime.colonTime;
}
}
説明:: initDateTimeはdateTimeの新しいインスタンスを割り当て、そのため、我々はそれが怠惰な初期化したいと、私が述べたようにdatetime.colonTimeが、(その後nullである
コードは、次のようなものです前)。 スレッドAがメソッドに入り、スケジューラがinitDateTime()を実行する直前にスレッドAを停止すると、 Thread Bがrunst getColonTime()を呼び出すと、datetimeがまだnullであり、それが初期化されていることがわかります。 datetime.colonTimeはnullであるため、2番目のブロックは実行され、datetime.colonTimeはStringBuilderの値を取得します。 スケジューラがこの行とreturn文の間でスレッドを停止し、スレッドAを再開すると、次のようになります。 initDateTimeが呼び出される直前にAが停止したので、AはのinitDateTime datetime.colonTimeを再びnullに設定します。スレッドAは2番目のifブロックを入力しますが、スケジューラはdatetime.colonTime = sb.toString()の前にAを中断します。が呼び出されます。結論として、dateTime.colonTimeはまだnullです。 スケジューラはBを再開し、メソッドはnullを返します。
getColonTime()をMyDateTimeの単一(最終)インスタンスに呼び出す多数のスレッドを持つことによって競合状態を引き起こそうとしましたが、まれにしかまれにしか失敗しませんでした。( JUnit "test"?
まず競合状態を引き起こすためにデバッガを使用することができます。私。スレッドを開始し、いくつかのブレークポイント(ifの間のようなもの)にキャッチして、別のブレークポイントを開始します。 RCがどのように起こったのかを知った後(あなたは今のところそれがないようです)、成功した単体テストを書くことができます – pupssman
私はあなたが 'return datetimeに到達する方法を見ていません。colonTime; 'を返し、nullを返します。あなたはhh:mm文字列をどのように構築しているかに問題はないと確信していますか?たぶんあなたの質問にそのコードを追加して、それを見ることができます。 – Windle
なぜそれが起こることができるか説明しました。それほど明白ではないと認めなければなりません。 – user3001