2017-01-02 15 views
2

安全なこのクラスのスレッドを作成し、私は、以前の試験の質問から以下の非スレッドセーフコードがあります。私は受験のために勉強しています

class Q3 { 
    private boolean f[] = new boolean[20]; 

    public Q3() { 
     for (int j = 0; j < 20; j++) { 
      f[j] = true; 
     } 
    } 

    public void negate(int a, int b) { 
     for(int j = a; j < b; j++) { 
      f[j] = !f[j]; 
     } 
    } 

    public void swap(int a, int b) { 
     boolean temp = f[a]; 
     f[a] = f[b]; 
     f[b] = temp; 
    } 
} 

が、私はそれには、以下の調整を行うことにより、スレッドセーフで作られました:

class Q3 { 
    private boolean f[] = new boolean[20]; 

    public Q3() { 
     for (int j = 0; j < 20; j++) { 
      f[j] = true; 
     } 
    } 

    synchronized void negate(int a, int b) { 
     for (int j = a; j < b; j++) { 
      f[j] = !f[j]; 
     } 
    } 

    synchronized void swap(int a, int b) { 
     boolean temp = f[a]; 
     f[a] = f[b]; 
     f[b] = temp; 
    } 
} 

しかし、元のコードがスレッドセーフではない理由を誰かに説明できますか?コードがスレッドセーフであることを保証する方法を知っていますが、なぜコードが/スレッドセーフであるとはまだ分かりませんか?

+0

'Q3'クラスの使用方法を教えてもらえますか? –

+0

これは実際に何の文脈でも使われていないのですが、問題はコードのスレッドを安全にするように頼んでいます。なぜなら、なぜスレッドセーフではないのだろうかということだけです。スレッドセーフであるかどうかを区別する方法を知りたいのですが –

+0

解決策を投稿していたときに最新の質問が削除されました。 'android:minSdkVersion =" 10 "'は ''になるはずです。あなたのビルドは失敗する必要があります –

答えて

1

2つのスレッドが同時にネゲートとスワップを呼び出し、すべてのインデックスが最初に値が真であるとします。今度は、両方のスレッドが同時に4番目のインデックスでvalue = trueを読み込むとします。第1スレッドはネゲートを呼び、4番目の要素を否定すると同時にfalseになります。同時に2番目のスレッドは4番目の要素を読み取り、5番目の要素にスワップします。したがって、この場合の最終結果は、4番目のインデックス値= false 5番目のインデックス値=真となります。

私たちは実行順序を予測できないので、別の実行シナリオになる可能性があります。 スレッド1の読み込み4番目の要素がfalseになると、スレッド1が更新された後にスレッド2が値を読み取るため、falseと読み込み、この値を5番目の要素に置き換えます。したがって、この場合、最終結果は4番目のインデックス値= trueと5番目のインデックス= falseです。 したがって、最終行は、同期を行わないとスレッドの実行順序を予測できず、予期しない結果が発生する可能性があります。だから、あなたが同期を言うとき、これらの2つのメソッドは決して一緒に呼び出されることはありません。そのため、同じインデックス要素を複数のスレッドが同時に読み書きすることはできません。

2

この回答は、複数のスレッドが同じスレッドQ3オブジェクトのインスタンスです。二つの別々のスレッドが以下が起こる可能性があり、コールswap()とインターリーブ両方にあった場合

public void swap(int a, int b) { 
    boolean temp = f[a]; 
    f[a] = f[b]; 
    f[b] = temp; 
} 

Thread one: 
boolean temp = f[a]; 
f[a] = f[b]; 

Thread two: 
boolean temp = f[a]; // his temp = f[b], wrong! 

Thread one: 
f[b] = temp;   // f[b] = f[b], no swap! 

Thread two: 
f[a] = f[b]; 
f[b] = temp;   // f[a] = f[b], wrong 

この最終結果がそのf[a]f[b]の両方である例としてswap()方法を取ります後者の値で終わります。両方のスレッドです。これは明らかにあなたが望むものではありません。 swap()メソッドを​​にすると、指定されたスレッドがそのメソッドをアトミックに実行することが保証されます。すなわち、指定されたスレッドはメソッド全体を単独で完了するか、間に何も入れずに完了します。

+0

ああ、私はあなたが今言っていることを理解していると思う、ありがとう! –

+0

@ JohnP.Lally upvoteは可能ですか? –

+0

私はしようとしたが、私は15未満の評判を持っているので、それは私を許さないだろう –

関連する問題