ホームページ  >  記事  >  Java  >  Java 同期ブロックの使用方法の詳細な紹介

Java 同期ブロックの使用方法の詳細な紹介

黄舟
黄舟オリジナル
2017-03-24 10:58:231522ブラウズ

Java 同期ブロックは、メソッドまたはコード ブロックを同期済みとしてマークするために使用されます。 Java 同期ブロックは競合を避けるために使用されます。この記事では次の内容を紹介します:

  • Java同期キーワード(同期)

  • インスタンスメソッドの同期

  • インスタンスメソッドの同期ブロック

  • 静的メソッドの同期ブロック

  • Java 同期の例

  • Java 同期キーワード (synchronized)

  • Java の同期ブロックは synchronized とマークされます。 Java の同期ブロックは、特定の
オブジェクト

上で同期されます。オブジェクト上で同期されるすべての同期ブロックは、同時に 1 つのスレッドによってのみ入力および実行できます。この同期ブロックに入るのを待っている他のすべてのスレッドは、この同期ブロックを実行しているスレッドが

終了

するまでブロックされます。 4 つの異なる同期ブロックがあります:

インスタンス メソッド

  1. 静的メソッド

  2. インスタンス メソッドの同期ブロック

  3. 静的メソッドの同期ブロック

  4. 上記の同期ブロックはすべて同期されていますさまざまなオブジェクトに。実際にどの同期ブロックが必要になるかは、状況によって異なります。

  5. インスタンス メソッドの同期

以下は、同期されたインスタンス メソッドです:

public synchronized void add(int value){
this.count += value;
 }

メソッド宣言内の synchronized キーワードに注意してください。これにより、メソッドが同期であることが Java に伝えられます。

Java インスタンス メソッドの同期は、メソッドを所有するオブジェクトで同期されます。このようにして、各インスタンスのメソッドの同期は、異なるオブジェクト、つまりメソッドが属するインスタンス上で同期されます。インスタンス メソッド同期ブロック内で実行できるスレッドは 1 つだけです。複数のインスタンスが存在する場合、スレッドは一度に 1 つのインスタンス同期ブロックで操作を実行できます。インスタンスごとに 1 つのスレッド。

静的メソッドの同期

静的メソッドの同期は、インスタンス メソッドの同期メソッドと同じであり、synchronized キーワードも使用します。 Java の静的メソッドの同期は次のとおりです。

public static synchronized void add(int value){
 count += value;
 }

同様に、ここでの synchronized キーワードは、このメソッドが同期されていることを Java に伝えます。

静的メソッドの同期とは、メソッドが配置されているクラス オブジェクトでの同期を指します。クラスは Java 仮想マシン内の 1 つのクラス オブジェクトにのみ対応できるため、同じクラス内の静的同期メソッドを同時に実行できるスレッドは 1 つだけです。

異なるクラスの静的同期メソッドの場合、1 つのスレッドが各クラスの静的同期メソッドを待機せずに実行できます。クラス内のどの静的同期メソッドが呼び出されるかに関係なく、クラスは同時に 1 つのスレッドによってのみ実行できます。

インスタンス メソッド内の同期ブロック

場合によっては、メソッド全体を同期する必要はなく、メソッドの一部を同期する必要があります。 Java はメソッドの一部を同期できます。

非同期 Java メソッドの同期ブロックの例を以下に示します。

public void add(int value){

    synchronized(this){
       this.count += value;
    }
  }

例では、Java 同期ブロック コンストラクターを使用して、コードのブロックを同期済みとしてマークします。このコードは同期メソッドのように実行されます。

Java 同期ブロック コンストラクターはオブジェクトをかっこで囲んでいることに注意してください。上記の例では、add メソッドを呼び出すインスタンス自体である「this」が使用されています。同期コンストラクタ内の括弧で囲まれたオブジェクトをモニタオブジェクトと呼びます。上記のコードはモニター オブジェクトの同期を使用しており、同期インスタンス メソッドは呼び出し元メソッド自体のインスタンスをモニター オブジェクトとして使用します。

同じモニター オブジェクトに同期された Java メソッド内で実行できるスレッドは一度に 1 つだけです。

次の 2 つの例はどちらも、呼び出されるインスタンス オブジェクトを同期するため、同期実行の効果は同等です。

public class MyClass {

   public synchronized void log1(String msg1, String msg2){
      log.writeln(msg1);
      log.writeln(msg2);
   }

   public void log2(String msg1, String msg2){
      synchronized(this){
         log.writeln(msg1);
         log.writeln(msg2);
      }
   }
 }

上の例では、2 つの同期されたブロックのいずれかのメソッドで一度に 1 つのスレッドのみを実行できます。

2 番目の同期ブロックがこのインスタンス オブジェクトで同期されていない場合、スレッドによって 2 つのメソッドが同時に実行される可能性があります。

静的メソッドの同期ブロック

上記と同様に、静的メソッドの同期の例を 2 つ示します。これらのメソッドは、そのメソッドが属するクラス オブジェクト上で同期されます。

public class MyClass {
    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
  }

これら 2 つのメソッドは、スレッドから同時にアクセスすることはできません。

2 番目の同期ブロックが MyClass.class オブジェクトで同期されていない場合。これにより、これら 2 つのメソッドにスレッドから同時にアクセスできるようになります。

Java 同期インスタンス

次の例では、2 つのスレッドが開始され、どちらも Counter クラスの同じインスタンスの add メソッドを呼び出します。同期はメソッドが属するインスタンス上で行われるため、メソッドに同時にアクセスできるスレッドは 1 つだけです。

public class Counter{
     long count = 0;

     public synchronized void add(long value){
       this.count += value;
     }
  }
  public class CounterThread extends Thread{

     protected Counter counter = null;

     public CounterThread(Counter counter){
        this.counter = counter;
     }

     public void run() {
    for(int i=0; i<10; i++){
           counter.add(i);
        }
     }
  }
  public class Example {

    public static void main(String[] args){
      Counter counter = new Counter();
      Thread  threadA = new CounterThread(counter);
      Thread  threadB = new CounterThread(counter);

      threadA.start();
      threadB.start();
    }
  }

创建了两个线程。他们的构造器引用同一个Counter实例。Counter.add方法是同步在实例上,是因为add方法是实例方法并且被标记上synchronized关键字。因此每次只允许一个线程调用该方法。另外一个线程必须要等到第一个线程退出add()方法时,才能继续执行方法。

如果两个线程引用了两个不同的Counter实例,那么他们可以同时调用add()方法。这些方法调用了不同的对象,因此这些方法也就同步在不同的对象上。这些方法调用将不会被阻塞。如下面这个例子所示:

public class Example {

   public static void main(String[] args){
     Counter counterA = new Counter();
     Counter counterB = new Counter();
     Thread  threadA = new CounterThread(counterA);
     Thread  threadB = new CounterThread(counterB);

     threadA.start();
     threadB.start();
   }
 }

注意这两个线程,threadA和threadB,不再引用同一个counter实例。CounterA和counterB的add方法同步在他们所属的对象上。调用counterA的add方法将不会阻塞调用counterB的add方法。

以上がJava 同期ブロックの使用方法の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。