2017-10-24 7 views
0

2つのスレッドがあり、これらのスレッドでStudentオブジェクトの異なるメソッドを実行します。問題は、このコードを実行するとt2スレッドが同期ブロックを完了するのを待つことです。異なる方法で異なるオブジェクトをロックする方法はありますか?

なぜt1が完了するのを待っていますか?どのようにしてお互いにブロックすることなく、異なる方法で異なるオブジェクトをロックすることができますか?

これは主な方法です。

Student student = new Student(); 
Thread t1 = new Thread(() -> { 
    try { 
     student.addA(); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex); 
    } 
}); 

Thread t2 = new Thread(() -> { 
    try { 
     student.addB(); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex); 
    } 
}); 

t1.start(); 
t2.start(); 

ここは学生クラスです。

public class Student { 

    private Integer a = 0; 
    private Integer b = 0; 

    public void addA() throws InterruptedException{ 
     System.out.println("addA start"); 
     synchronized(a){ 
      System.out.println("addA sync start"); 
      a++; 
      Thread.sleep(5000); 
     } 
     System.out.println("addA end"); 
    } 

    public void addB() throws InterruptedException{ 
     System.out.println("addB start"); 
     synchronized(b){ 
      System.out.println("addB sync start"); 
      b++; 
      Thread.sleep(5000); 
     } 
     System.out.println("addB end"); 
    } 

} 

答えて

5

この:

private Integer a = Integer.valueOf(0); 
private Integer b = Integer.valueOf(0); 

the result of Integer.valueOf(0) is cachedので、あなたは実際には同じオブジェクトで同期をとるいる:

private Integer a = 0; 
private Integer b = 0; 

は実際にこれと同じです。

new Integer(0)を使用すると、異なるIntegerインスタンスを取得できます。

しかし、これはただの道問題一回の反復を蹴っている:

a++; 

は実際には次のとおりです。

a = Integer.valueOf(a.intValue() + 1); 

ので、あなたが潜在的に少なくともaまで、再び同じ問題に遭遇することができます " s値がInteger.valueOfメソッドによってキャッシュされた値の範囲を超えています(少なくとも127ですが、実装に依存します)。すぐにこの行が実行されているように、別のスレッドがその同期ブロックを入力することができますので、

a = new Integer(a.intValue() + 1); 

しかし、変更可能なリファレンスに同期することはかなり悪い考えは次のとおりです。

あなたは同じトリックを適用することができます。 (既にブロックされているものではなく、後で​​に達するスレッド)。

private final Object aLock = new Object(); 
private final Object bLock = new Object(); 

をして代わりに、それに対応しabのこれらで同期:

代わりに、あなたはabごとに別々のロックオブジェクトを作成する必要があります。

関連する問題