2016-10-14 7 views
1

1)同期されている場合(this)は、2つのスレッドのいずれかがfactorインスタンスをロックし、ループが終了するまで変数valの値を増やすことを意味します。 同期された(this)は、他のインスタンス変数を使用しないことを意味します。 synchronizedブロックの中でfactorインスタンスの変数のみを使用する必要がありますか?Javaマルチスレッド同期の確認?

2)ここで同期(追加)とは、factorインスタンスクラスのval変数ではなく、add変数のみを使用する必要があるということですか?

この同期ブロックに関する大きな混乱があります。 私が理解したことは、同期ブロックがオブジェクトのインスタンスをロックし、操作を保護し、スレッドを安全にすることです。しかし、異なるインスタンスを使用するということは、その特定のインスタンス変数だけをガードする必要があることを意味します。誰もがこの

class Factor implements Runnable 
{ 
int val = 0; 
Addition addtion = new Addition(); 

@Override 
public void run() 
{ 

    currInsLock(); 
    diffInsLock(); 
} 

// locking on the current instance which is this 
// we will use synchronized(this) 

public void currInsLock() 
{ 
    synchronized (this) 
    { 
     for(int i=0;i<100;i++) 
     { 
       try 
        { 
        Thread.sleep(100); 
        } 
       catch (InterruptedException e) 
       { 
         e.printStackTrace(); 
       } 
     System.out.println(Thread.currentThread().getName()+"---val value lock on this obj -->"+val++); 

     } 
    } 
} 



// locking on the different instance 
public void diffInsLock() 
{ 
    synchronized (addtion) 
    { 

     for(int i=0;i<100;i++) 
     { 
       try 
        { 
        Thread.sleep(100); 
        } 
       catch (InterruptedException e) 
       { 
         e.printStackTrace(); 
       } 
     System.out.println(Thread.currentThread().getName()+"---val value lock on addition obj -->"+val++); 
     System.out.println(Thread.currentThread().getName()+"---add value lock on addition obj -->"+addtion.add++); 
     } 
    } 
} 

} 

追加クラスの下に提供されているコードと関連についての深さの概念で説明できます:

public class Addition 
{ 
    public int add=0; 
} 

public class ConcurrentDoubt { 

public static void main(String[] args) 
{ 
    Factor factor=new Factor(); 

    Thread thread1=new Thread(factor); 
    Thread thread2=new Thread(factor); 

    thread1.start(); 
    thread2.start(); 

} 
} 

答えて

2

何をオブジェクトのモニターとして使用することは本当にないですメインクラス重要なのは、どのオブジェクトでもかまいませんが、理想的にはオブジェクトのモニターとしてを使うべきではなく、private final Objectインスタンスコードの外側にオブジェクトのモニタとしてクラスのインスタンスを使用すると、クラスが適切に動作しなくなる可能性があるため、クラスをよりよく保護するためです。

重要なポイントは、プロテクトしたいものが外部のアクセス/変更されている場合は、保護したいもの(メンバ変数、クラスインスタンスなど)を変更またはアクセスしたいときはいつでも、同じオブジェクトのモニタを使用することです。​​ブロックまたは別のオブジェクトのモニターでは、同時アクセスまたは変更を防ぐことができないため、コードはスレッドセーフではありません。実際には、特定のオブジェクトのモニタに対して​​ブロックで保護されたコードを実行できるスレッドは1つだけなので、同じものを保護する2つのオブジェクトモニタがあります。

ここでは、メンバ変数valを保護するオブジェクトのモニタとしてthisaddtionを使用して、コードがスレッドセーフではないため、同じオブジェクトのモニタを使用する必要があります。

あなたのメンバ変数valを保護するためにオブジェクトのモニターとしてthisを使用したいと仮定すると、あなたのコードではなく次のようになります。

synchronized (addtion) { 
    for(int i=0;i<100;i++) { 
     ... 
     synchronized (this) { 
      System.out.println(
       Thread.currentThread().getName() + 
       "---val value lock on addition obj -->" + val++ 
      ); 
     } 
     System.out.println(
      Thread.currentThread().getName() + 
      "---add value lock on addition obj -->" + addtion.add++ 
     ); 
    } 
} 
+1

OP:」...別のインスタンスを使用して、本当にそれだけのことを守る必要があることを意味し特定のインスタンス変数は他のインスタンス変数ではありません... " - スレッドの相互排除が強調される必要があると思います。そのため、ブロック内のデータへのアクセスはすべてスレッドごとに順序付けられます。 –

+0

フィードバックのための@VictorSorokinthxしかし、率直に言って、私はまだOPのこの文をはっきりと理解していません。しかし、あなたが提案しているのは何とか 'あなたのコードはスレッドセーフではありません。なぜなら、同時アクセスや改変を防ぐことができないからです。 ' –

+0

@VictorSorokinあなたの発言を追加するために私の答えがちょっと変わったよ、 –

関連する問題