質問

きのいずれかの同期の方法で同期をブロックを例に?

役に立ちましたか?

解決

  

の誰も私の例と同期ブロックを超える同期方法の利点を伝えることはできますか?ありがとうございました。

ブロックの上に同期メソッドを使用しての明確な利点がありません。

おそらく唯一の1は(私は利点にそれを呼び出すことはありません)を使用すると、オブジェクト参照thisを含める必要はありませんです。

方法:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

ブロックます:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

を参照してください?まったく利点はありません。

メソッドを同期すると、オブジェクト全体をロックします一方、あなたがロックとして別のオブジェクトを使用することができますので、

ブロックの の大部分は柔軟で、けれどもの方法に比べて利点を持っています。

の比較:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

対。

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

:メソッドが増大した場合、

また、あなたはまだ同期セクション区切りを保つことができます

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}

他のヒント

唯一の本当の違いは、同期ブロックは、それが同期するオブジェクトを選択することができるということです。同期方法は、'this'(または同期クラスのメソッドに対応するクラスのインスタンス)を使用することができます。例えば、これらは意味的に等価である

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}
それは、多くの場合、メンバ変数いずれかのオブジェクトの関連するロックを競合することができるので、

後者は、より柔軟です。あなたはメソッド内で前と後のブロックが、まだ実行並行コードを持っている可能性があるため、また、より細かいです。もちろん、あなたが同じように簡単に別の非同期メソッドに並行コードをリファクタリングすることにより、同期メソッドを使用することができます。コードがより分かりになる方使用ます。

同期方法

メリット:

  • IDEを切り換えて表示することができ、同期されます。
  • 構文をコンパクト化に寄与しています。
  • 勢力への同期化ブロックに分けます。

連結:

  • 同期化させることなどで外部同期をかなければならない。
  • では、硬めの動きコード外部の同期化ブロックです。

同期ブロック

メリット:

  • で使用するためのprivate変数、ロスエロエスデイキケ記で強制的にロックが滞在中のクラスです。
  • 同期ブロックすると検索への参照を可変となります。

連結:

  • の構文が複雑などにより、コード難読み出します。

個人的に好きですから利用同期方法と授業のみが必要なものに同期します。このようなクラス小さくするべきでなければならないと考えておくのに同期します。その他なについて注意する必要はあり同期します。

主な違いは、ご利用の場合は、同期ブロックがロックオブジェクト以外の この を可能にする自由度は飛躍的に向上します。

とのメッセージをお願いしまのキューおよび複数のメッセージ、生産者と消費者です。てにおいて生産者が互いに干渉すが、消費者の動きを取得するメッセージを待たずに生産者である。まずにオブジェクトを作成し

Object writeLock = new Object();

びこれからは各生産者の希望を追加する新しいメッセージまでロックする:

synchronized(writeLock){
  // do something
}

が消費者にも読み取り、生産者がロックされています。

同期方法

同期の方法は二つです。
まず、一つのスレッドが実行同期の方法でオブジェクト、その他のすべてのスレッド呼び出しで同期方法が同じオブジェクトをブロックの停止"を実行しますので、最初のスレッドが実際どのように使われているかオブジェクトです。

第二に、同期方法退と、自動的に設立が起こる前と後続の呼び出しの同期方法が同じオブジェクトです。この保証の変更の状態でオブジェクトが可視にすべてのスレッド)。

このコンストラクタは同期することに同期をキーワードコンストラクタでは、構文エラーとなります。同期のコンストラクタがな意味でのみ、スレッドを生成するオブジェクトへのアクセスを持つべきであるからに追い込まれています。

同声明

同期とは異なりの方法で同期計算書を指定する必要があるオブジェクトに固有のロック最もよく使っているこの同期アクセスリストまたは地図にもならないようにしたいブロックへのアクセスすべてのメソッドのオブジェクトです。

Q:本質的なロックと同期 同期を中心に構成されている内部エンティティの本質的なロックまたはモニターロックが解除されます。(APIの仕様が多いとはこの事業体として、"モニター") 固有ロックの役割を果たつの側面から同期強制専用のオブジェクトへのアクセスの状態を確立が起こる前に関係するのに欠かせないます。

各オブジェクトに固有のロックを関連付けられています。規則にしたがって、スレッドのニーズ専属の一貫したオブジェクトへのアクセスの分野である、オブジェクトの本質的なロックのアクセスし、その後リリース本来のロックができます。スレッドは自分の本来のロックの間に取得した、ロックされ、ロックが解除されます。どのスレッドが所有する本質的なロック、他のスレッドが取得でき、同じロックになっています。その他のスレッドがブロックが取得を試み、ロックが解除されます。

package test;

public class SynchTest implements Runnable {  
    private int c = 0;

    public static void main(String[] args) {
        new SynchTest().test();
    }

    public void test() {
        // Create the object with the run() method
        Runnable runnable = new SynchTest();
        Runnable runnable2 = new SynchTest();
        // Create the thread supplying it with the runnable object
        Thread thread = new Thread(runnable,"thread-1");
        Thread thread2 = new Thread(runnable,"thread-2");
//      Here the key point is passing same object, if you pass runnable2 for thread2,
//      then its not applicable for synchronization test and that wont give expected
//      output Synchronization method means "it is not possible for two invocations
//      of synchronized methods on the same object to interleave"

        // Start the thread
        thread.start();
        thread2.start();
    }

    public synchronized  void increment() {
        System.out.println("Begin thread " + Thread.currentThread().getName());
        System.out.println(this.hashCode() + "Value of C = " + c);
//      If we uncomment this for synchronized block, then the result would be different
//      synchronized(this) {
            for (int i = 0; i < 9999999; i++) {
                c += i;
            }
//      }
        System.out.println("End thread " + Thread.currentThread().getName());
    }

//    public synchronized void decrement() {
//        System.out.println("Decrement " + Thread.currentThread().getName());
//    }

    public int value() {
        return c;
    }

    @Override
    public void run() {
        this.increment();
    }
}

クロスチェックの異なる出力との同期方法は、ブロックとなく同期します。

注:を同期する方法とブロックはClassオブジェクトで作業の静的

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}
Javaコンパイラは、バイトコードへのソースコードを変換し、

するとき、それは非常に異なった同期方法及び同期ブロックを処理します。

JVMが同期メソッドを実行する

、実行中のスレッドは、それが自動的にオブジェクトのロックを獲得し、メソッドのmethod_info構造がACC_SYNCHRONIZEDフラグが設定されていることを識別する、ロック方法、およびリリースを呼び出します。例外が発生した場合、スレッドは自動的にロックを解除します。

メソッドブロックの同期、一方で、オブジェクトのロックと例外処理を取得するためのJVMの組み込みサポートをバイパスし、機能を明示的にバイトコードで書かれている必要があります。あなたがsynchronizedブロックでメソッドのバイトコードを読んでいる場合は、この機能を管理するためにダース以上の追加の操作が表示されます。

これは、同期メソッドと同期ブロックの両方を生成する呼び出しを示しています。

public class SynchronizationExample {
    private int i;

    public synchronized int synchronizedMethodGet() {
        return i;
    }

    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }
}

synchronizedMethodGet()方法は、以下のバイトコードを生成します。

0:  aload_0
1:  getfield
2:  nop
3:  iconst_m1
4:  ireturn

そして、ここでsynchronizedBlockGet()メソッドからバイトコードです:

0:  aload_0
1:  dup
2:  astore_1
3:  monitorenter
4:  aload_0
5:  getfield
6:  nop
7:  iconst_m1
8:  aload_1
9:  monitorexit
10: ireturn
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow
<時間>

同期方法とブロックとの間の1つの大きな違いは、同期ブロックは、一般的ロックの範囲を減少させることです。ロックの範囲は、性能に反比例するように、その常により良いコードの唯一のクリティカルセクションをロックします。同期ブロックを使用しての最高の例の一つは、二重/ されますA>ここで、代わりに全体getInstance()方法をロックする我々は唯一のシングルトンインスタンスを作成するために使用されるコードのクリティカルセクションをロックします。ロックは、1つのまたは2回だけ必要とされるので、これは大幅にパフォーマンスが向上します。

synchronizedメソッドを使用している間、あなたは両方の静的な同期および非静的メソッド同期を混ぜた場合、余分な世話をする必要があります。

ほとんどの場合、私は、これは、リストへのアクセスを同期するか、マップするために使用しますが、私は、オブジェクトのすべてのメソッドへのアクセスをブロックする必要はありません。

次のコードでリストを修正する1つのスレッドマップを変更しているスレッドを待ってブロックしないであろう。メソッドがオブジェクト上で同期された場合は、それぞれの方法は、彼らが作っているの変更が競合しないだろうにもかかわらず待たなければならない。

private List<Foo> myList = new ArrayList<Foo>();
private Map<String,Bar) myMap = new HashMap<String,Bar>();

public void put( String s, Bar b ) {
  synchronized( myMap ) {
    myMap.put( s,b );
    // then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public void hasKey( String s, ) {
  synchronized( myMap ) {
    myMap.hasKey( s );
  }
}

public void add( Foo f ) {
  synchronized( myList ) {
    myList.add( f );
// then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public Thing getMedianFoo() {
  Foo med = null;
  synchronized( myList ) {
    Collections.sort(myList);
    med = myList.get(myList.size()/2); 
  }
  return med;
}

複数の同時なく、競合しないものが同時に上に行くことができるようにsynchronizedブロックを使用すると、あなたは、複数のシンクロナイザを持つことができます。

同期方法は、リフレクションAPIを使用して確認することができます。これは、このようなは、モデル内のすべてのメソッドは同期化されているなど、いくつかの契約を、テストするのに便利です。

次のコードは、ハッシュテーブルの全ての同期メソッドを印刷

for (Method m : Hashtable.class.getMethods()) {
        if (Modifier.isSynchronized(m.getModifiers())) {
            System.out.println(m);
        }
}
同期ブロック使用上の

重要な注意:注意!あなたがロックオブジェクトとして使用するものを

user2277816からのコードスニペットは、上記目的をロックとして使用されるリテラル文字列を参照し、その中にこの点を示しています。 その文字列リテラルは自動的にJavaで抑留され、あなたが問題を見始めるべきで実現:リテラル「ロック」に同期するコードのすべての部分を、同じロックを共有!これは簡単にコードの完全に無関係片と、デッドロックにつながることができます。

それはあなたがして注意する必要があるだけでStringオブジェクトではありません。オートボクシングとのvalueOfメソッドは値に応じて、同じオブジェクトを再利用することができるので、箱入りのプリミティブは、また危険である。

詳細については以下を参照してください。 ます。https:/ /www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reusedする

るのではなく、ロックの方法が失礼になることもある。なぜロックのコードにアクセスしない他の資源によるロック全体の方法です。それぞれのオブジェクトはロックを作成できダミーオブジェクト実施のブロックレベルに同期します。このブロックレベルがより効率的なロックの方法。

この一例

の方法を

class MethodLevel {

  //shared among threads
SharedResource x, y ;

public void synchronized method1() {
   //multiple threads can't access
}
public void synchronized method2() {
  //multiple threads can't access
}

 public void method3() {
  //not synchronized
  //multiple threads can access
 }
}

ブロックレベル

class BlockLevel {
  //shared among threads
  SharedResource x, y ;

  //dummy objects for locking
  Object xLock = new Object();
  Object yLock = new Object();

    public void method1() {
     synchronized(xLock){
    //access x here. thread safe
    }

    //do something here but don't use SharedResource x, y
    // because will not be thread-safe
     synchronized(xLock) {
       synchronized(yLock) {
      //access x,y here. thread safe
      }
     }

     //do something here but don't use SharedResource x, y
     //because will not be thread-safe
    }//end of method1
 }

[編集]

のための Collection のように VectorHashtable 彼らは同時 ArrayList または HashMap ない、必要なセットで同期をキーワードを起動蔵の同期方法

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map
List myList = Collections.synchronizedList (myList); // single lock for the entire list

唯一の違い: 同期ブロックできる粒状のロックと同期方法

基本的には synchronized ブロックまたはメソッドで書き込むのに使用されるスレッドに対して安全コードを回避することによるメモリの矛盾。

この質問は非常に古い多くのものが変わりの中で過去7年間務める。新しいプ構築においては、これまでに開発されたスレッドの安全性です。

で表現できるスレッドの安全性により高度な並行処理APIの代わりに synchronied ブロックとなります。このドキュメント ページ 提供プログラムの構築をスレッドの安全性です。

ロックオブジェクト ポロックとイディオムを簡単に多くの併願います。

執行者 を定義する高レベルAPIを立ち上げを管理す。Executor実装を提供するjava.util.同時提供のスレッドプール管理に適した大きなスケールアプリケーション.

兼職の状況所蔵 容易に管理可能な大規模なコレクションデータを大幅に削減することが可能に同期します。

原子力変数 しての特徴を最小化するような同期をやめたならもう放送すんな記憶の一貫性。

ThreadLocalRandom (JDK7)を分離することで効率的かつ世代の乱数から複数のスレッド)。

よりよい交換による同期は ReentrantLock, を使用する Lock API

再入可能な相互排他ロックと同じ基本行動と意味論としての暗黙の監視ロックを使用してアクセスの同期方法及び結し、かつ拡張機能

例とロック:

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

参照 java.util.兼職の状況java.util.兼職の状況.原子 パッケージにおいても、他のプログラミングを構築します.

このような関連する質問も

同期vsロック

同期方法は、すべてのオブジェクトのロックに使用されます 同期ブロックは、特定のオブジェクトをロックするために使用されている

一般的に、これらは主に、暗黙的なこのオブジェクト対使われているオブジェクトのモニターについての明示的なこと以外同じです。私は時々見落とされていると思います同期方法の一つの欠点は、あなたに同期させるために「this」参照を使用して同じオブジェクトにロック外部オブジェクトの可能性を開いたままにしているということです。あなたがそれに実行する場合、それは非常に微妙なバグすることができます。内部明示的なオブジェクトまたは他の既存のフィールドに同期すると、完全同期をカプセル化し、この問題を回避することができます。

すでにここ同期ブロックは、同期機能は唯一の「この」使用していますロックオブジェクト、ユーザー定義変数を使用することができます言ったように。そしてもちろん、同期する必要がありますあなたの関数の領域で操作することができます。 しかし、誰もが同期機能と全体の機能をカバーしてブロックの間には差は「この」などのロックオブジェクトを使用していないと述べています。それは本当ではないです、違いは、両方の状況で生成されるバイトコードです。同期ブロックの使用の場合には「この」への参照を保持するローカル変数を割り当てなければなりません。そして、(あなたは機能のほんの数の数を持っている場合ではない関連)、結果として、我々は機能のために少し大きなサイズになります。

あなたがここに見つけることができるの違いのより詳細な説明: http://www.artima.com/insidejvm/ed2/threadsynchP.htmlする

同期の方法の場合には、ロックオブジェクトに取得されます。あなたが同期ブロックで行く場合しかし、あなたはロックが取得されるオブジェクトを指定するオプションがあります。

例:

    Class Example {
    String test = "abc";
    // lock will be acquired on String  test object.
    synchronized (test) {
        // do something
    }

   lock will be acquired on Example Object
   public synchronized void testMethod() {
     // do some thing
   } 

   }

私は、これは古い質問ですけど、ここでの回答の私の迅速な読み取りと、私は本当に誰もが時々synchronized方法は、を間違ったのロックであってもよいことに言及表示されませんでした。
Javaの並行処理から、実際には(PG 72。):

public class ListHelper<E> {
  public List<E> list = Collections.syncrhonizedList(new ArrayList<>());
...

public syncrhonized boolean putIfAbsent(E x) {
 boolean absent = !list.contains(x);
if(absent) {
 list.add(x);
}
return absent;
}

上記のコードは、スレッドセーフであることのの外観]を有します。しかし、現実にはそうではありません。この場合、ロックは、クラスのインスタンスで得られます。しかし、のリストについては、その方法を使用していない別のスレッドによって修正することが可能です。正しいアプローチは、使用することです。

public boolean putIfAbsent(E x) {
 synchronized(list) {
  boolean absent = !list.contains(x);
  if(absent) {
    list.add(x);
  }
  return absent;
}
}

上記のコードはをブロックするすべてのスレッド同期ブロックが完了するまでは、リストを修正することから、を変更しようとしているのリストの。

実際問題として、synchronizedブロック経由で同期する方法の利点は、彼らがより多くの馬鹿耐性であるということです。あなたがロックオンする任意のオブジェクトを選択することはできませんので、あなたは、文字列リテラルにロックやスレッドの下から出て変更されます可変フィールドの内容にロックのような愚かなことを行うために、同期メソッドの構文を誤用することはできません。

一方、同期方法では、オブジェクトへの参照を取得することができます任意のスレッドが取得し得ることから、ロックを保護することはできません。

民間最終ロックオブジェクトと一緒にsynchronizedブロックを使用すると、牛-orkersから独自のコードを保護に優れている間に

だから、メソッドの修飾子として同期使用すると、自分自身を傷つけるからあなたの牛-orkersを保護するのに優れています。

からJavaの仕様概要:http://www.cs.cornell.edu/andru/javaspec/17.doc.html

同期決§14.17)を計算への参照オブジェクト;その試みは行ロックを作るオブジェクトとな さらに進めるまでのロックのアクションが成功裡に終了致しました。...

同期方法(§8.4.3.5)を自動で行う、ロックアクション ときに呼び出され;その身体は実行されませんので、ロックのアクションが 成功裡に終了致しました。 このメソッドはインスタンスメソッド, ので、 ロックロックに関連するインスタンスで呼び出され このオブジェクトとして知られるこの実行中に のボディに法です。 このメソッドは、静的, でロックの ロックに関連するClassオブジェクトを表すクラス るのが発生する可能性があります。...

これらの記述んじゃないでしょうかはほとんど前の回答内容に間違いがないか確認し、同期方法が特に有のためのstaticメソッドが付いている方法を見つけ出すことを"を表すClassオブジェクトのクラスの方法が定義されています。"

編集:私は、もともとは考えられた引用符の実際のJavaの仕様明らかにこのページでは概要の説明の仕様

TLDR; ものをご利用 synchronized 修飾もの synchronized(this){...} 表現が synchronized(myLock){...} 場所 myLock 最終インスタンスの分野を持つ民間のオブジェクトです。


の違いを利用 synchronized 修飾子の宣言方法の synchronized(..){ } 表現の方法を体外です:

  • synchronized 修飾子で指定されたメソッドの署名
    1. が見える、生成されJavaDoc,
    2. はプログラムに算定によ 反射 検査方法の改質剤 を模倣しています。同期,
    3. によるタイピングおよびindention比 synchronized(this) { .... }, は、
    4. (IDE)は、クラスの概要コードの完成
    5. を利用し this オブジェクトとしてロックが宣言された非staticメソッドは、囲むクラスが宣言されて、静的な方法です。
  • synchronized(...){...} 表現できる
    1. への同期の実行の部分の方法は、
    2. 使用する内にコンストラクタまたは(静的)初期化ブロック
    3. 選べるロックオブジェクトをコントロールに同期します。

しかし、 synchronized 修飾子は synchronized(...) {...}this としてのロックオブジェクト( synchronized(this) {...}て、同じる。両方を使用し独自のインスタンスとしてのロックオブジェクトを同期させます。る恐れがあり、これは危険であるだけではなく、オブジェクト自体が 他の その他の外部オブジェクトまたはコードを実現したことにより参照するオブジェクトとしても同期ロックの可能性のある厳しい副作用の性能劣化や デッドロック).

そのためキャッシュフローをもとに利用 synchronized 修飾もの synchronized(...) 表現を併 this としてロックオブジェクトがロックオブジェクトにこのオブジェクトです。例えば:

public class MyService {
    private final lock = new Object();

    public void doThis() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }

    public void doThat() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }
}

も利用できます複数のロックオブジェクトが特別な注意を払う必要がある、将来予告なしに変更することながらないようなデッドロック使用時の入れ子構造があります。

public class MyService {
    private final lock1 = new Object();
    private final lock2 = new Object();

    public void doThis() {
       synchronized(lock1) {
          synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThat() and doMore().
          }
    }

    public void doThat() {
       synchronized(lock1) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doMore() may execute concurrently
        }
    }

    public void doMore() {
       synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doThat() may execute concurrently
        }
    }
}

と思い質問しての違い スレッドに対して安全シングルトン怠け者の初期化とのダブルチェックロック.いつもこのような記事がいを実装する必要があると特定のシングルトン.

これは伸びるこれはすごいる スレッドに対して安全シングルトン:

// Java program to create Thread Safe 
// Singleton class 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

 //synchronized method to control simultaneous access 
  synchronized public static GFG getInstance()  
  { 
    if (instance == null)  
    { 
      // if instance is null, initialize 
      instance = new GFG(); 
    } 
    return instance; 
  } 
} 

メリット:

  1. 怠け者の初期化が可能です。

  2. このスレッドで安全です。

連結:

  1. getInstance()メソッドは同期化での原因となり遅いパフォーマンとして複数のスレッドできないアクセスです。

この 怠け者の初期化とのダブルチェックロック:

// Java code to explain double check locking 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

  public static GFG getInstance() 
  { 
    if (instance == null)  
    { 
      //synchronized block to remove overhead 
      synchronized (GFG.class) 
      { 
        if(instance==null) 
        { 
          // if instance is null, initialize 
          instance = new GFG(); 
        } 

      } 
    } 
    return instance; 
  } 
} 

メリット:

  1. 怠け者の初期化が可能です。

  2. でもスレッドで安全です。

  3. 性能を抑えるためのキーワードで同期を克服です。●

連結:

  1. 初めてできます。

  2. として連結実績ダブルチェック固定方法救急できます 高性能マルチスレッド願います。

についてはこちらを参照ください記事詳しくは:

https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/

スレッドとの同期。 1)それは動作しませんスレッドで(これを)同期を使用しないでください。 (本)に同期してロックスレッドオブジェクトとして、現在のスレッドを使用します。各スレッドは他のスレッドとは独立しているので、同期の調整は行われません。 2)コードのテストはMac上のJava 1.6でメソッドの同期が動作しないことを示しています。 lockObjは、それが動作する上で同期させるすべてのスレッドの共通の共有オブジェクトである3)同期(lockObj)。 4)ReenterantLock.lock()と.unlock()ワーク。このためのJavaチュートリアルを参照してください。

次のコードは、これらの点を示しています。また、ArrayListのと同じ情報を失うことができますが、ベクトルに追加する多くのスレッドが任意の情報を失わないことを示すために、ArrayListのために置換されるだろうスレッドセーフなベクトルが含まれています。 0)現在のコードが原因競合状態に情報の損失を示しました A)現在の標識された行をコメントし、実行し、その上の行のコメントを解除し、この方法は、データを失うが、それはいけません。 B)逆工程A、B及びコメントを解除//終了ブロック}。そして、その結果にデータの損失を見ないように実行します C)予想通り、これは)、データを失う(上の同期参照、B、コメントを解除C.実行をコメントアウト。 すべてのバリエーションを完了する時間がない、このことができます願っています。 (この)上の同期、またはメソッドの同期動作するかどうか、あなたがテストしたJavaとOSのバージョンが明記してください。ありがとうございます。

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources 
     thread one may grab the resource expecting to update a particular 
     area but is removed from the CPU before finishing.  Thread one still 
     points to that resource.  Then thread two grabs that resource and 
     completes the update.  Then thread one gets to complete the update, 
     which over writes thread two's work.
     DEMO:  1) Run as is - see missing counts from race condition, Run severa times, values change  
            2) Uncomment "synchronized(countLock){ }" - see counts work
            Synchronized creates a lock on that block of code, no other threads can 
            execute code within a block that another thread has a lock.
        3) Comment ArrayList, unComment Vector - See no loss in collection
            Vectors work like ArrayList, but Vectors are "Thread Safe"
         May use this code as long as attribution to the author remains intact.
     /mf
*/ 

public class RaceCondition {
    private ArrayList<Integer> raceList = new ArrayList<Integer>(); // simple add(#)
//  private Vector<Integer> raceList = new Vector<Integer>(); // simple add(#)

    private String countLock="lock";    // Object use for locking the raceCount
    private int raceCount = 0;        // simple add 1 to this counter
    private int MAX = 10000;        // Do this 10,000 times
    private int NUM_THREADS = 100;    // Create 100 threads

    public static void main(String [] args) {
    new RaceCondition();
    }

    public RaceCondition() {
    ArrayList<Thread> arT = new ArrayList<Thread>();

    // Create thread objects, add them to an array list
    for( int i=0; i<NUM_THREADS; i++){
        Thread rt = new RaceThread( ); // i );
        arT.add( rt );
    }

    // Start all object at once.
    for( Thread rt : arT ){
        rt.start();
    }

    // Wait for all threads to finish before we can print totals created by threads
    for( int i=0; i<NUM_THREADS; i++){
        try { arT.get(i).join(); }
        catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }
    }

    // All threads finished, print the summary information.
    // (Try to print this informaiton without the join loop above)
    System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",
                MAX*NUM_THREADS, raceList.size(), raceCount );
    System.out.printf("Array lost %,d. Count lost %,d\n",
             MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );
    }   // end RaceCondition constructor



    class RaceThread extends Thread {
    public void run() {
        for ( int i=0; i<MAX; i++){
        try {
            update( i );        
        }    // These  catches show when one thread steps on another's values
        catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }
        catch( OutOfMemoryError oome ) { System.out.print("O"); }
        }
    }

    // so we don't lose counts, need to synchronize on some object, not primitive
    // Created "countLock" to show how this can work.
    // Comment out the synchronized and ending {, see that we lose counts.

//    public synchronized void update(int i){   // use A
    public void update(int i){                  // remove this when adding A
//      synchronized(countLock){            // or B
//      synchronized(this){             // or C
        raceCount = raceCount + 1;
        raceList.add( i );      // use Vector  
//          }           // end block for B or C
    }   // end update

    }   // end RaceThread inner class


} // end RaceCondition outter class
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top