Javaスレッドのスレッド同期


注意:wait notifyはすべてObjectの方法です
同期(ブロック):共有リソースへのアクセスによるデータの不一致を防止するモードです.
詳細はオペレーティングシステムを参照してください.
Javaでは、マルチスレッドのサポートにより、同期の制御は主に以下の方法、synchronized、wait()、notify()およびnotifyAll()によって行われ、以下に説明します.
Aキーワードsynchronized
Javaオブジェクトごとにロックがあり、共有リソースに複数のスレッドが同時にアクセスする場合は、synchronizeを使用してセキュリティを制御する必要があります.synchronizeはsynchronizeメソッドとsynchronizeブロックに分けられ、synchronizeブロックを使用する場合は、そのオブジェクトを取得するロック(synchronize(object)など)を表示する必要がありますが、メソッドは必要ありません.
JAvaのメモリモデルは、プロセスごとにプライマリメモリがあり、各スレッドには独自のメモリがあり、プライマリメモリからデータを取り出し、計算してプライマリメモリに格納します.
複数のスレッドの同僚が同じデータを操作すると、Aスレッドがメインメモリから取ったIの値が1になり、プラス1操作を行うと、BスレッドもIの値を取ってプラス2操作を行い、Aがメインメモリに2を格納し、Bも格納することで、Aの値(データベースの同時問題と同様)が上書きされます.
解決策はsynchronizeで、synchronized(I)を用いる.synchronizeで修飾される方法(ブロック)次の3段階の操作を1つの原子操作とする:データを取り、データを操作し、データを保存する.原子操作は中断されてはいけないことを知っているので、データの一致性を保証し、このように同じ時間に1つのスレッドだけが再実行され、性能に一定の影響を与える.これもsynchronizeの2番目の役割である:統一時間に1つのスレッドだけが再実行されることを保証する実行します.SOCKET接続を実現する際によく用いられる.
JAVAでは非FLOAT,LONGに対する原型の取和存操を原子として扱うことを規定している.実は1文字(32ビット)の取に対して、ビットの原始操作を保存して、FLOAT、LONGは2バイトの長さなので、それを取って、非原子操作に保存します.彼らも原子操作に変えたいなら、VOLATILEキーワードで修飾することができます
使用方法:
作用領域は主に2種類あります.
1.方法
2.コードブロック
synchronizedによって宣言される方法を同期方法と呼び、その修飾されたコードブロックを同期文と呼ぶ.同期方法であれ、同期文であれ、同期したと宣言された場合、同じ時点で同じオブジェクトの同期XXは同時にアクセスできませんが、異なるオブジェクト間の同期方法は互いに干渉しません.
具体的なインプリメンテーション(次のコードはクラス定義にあります):
同期方法:
Public synchronized void change() {
//
}
≪同期文|Synchronize文|oem_src≫:(効率の問題のため、同期文ブロックの使用を検討する場合があります)
    Public void change() {
               Synchronized(this) {
}
}
この同期文は現在のオブジェクトに対して使用され、コードを同期させたい場合があります.現在のオブジェクトとは関係なく、同期のロックをカスタマイズできます.次のようになります.
private byte[]  lock= new byte[0];
  Public void change() {
Synchronized(lock) {
}
}
カスタムロックの注意事項:
1クラス外部での参照の変更を防ぐためにprivateでなければなりません.
2可能であればgetメソッドを書き換え、オブジェクトのcloneを返します.それ自体ではありません.
その他の使用方法:
Synchronizedは、メソッド、コードブロックに加えて、静的メソッド、クラス、インスタンスにも使用できます.しかし、いずれも効率の問題があり、慎重に使用しなければならない.
Class Foo   {   
public synchronizedstatic void methodAAA()//    static    
{   
//….  
}  

  public void methodBBB()   { 
      synchronized(Foo.class)// class literal(       ) 
 } }


このような修飾は、クラスに対する宣言であるため、統一された時点で、修飾された部分は1つのオブジェクトだけが実行できることを意味します.
2.wait()/notify()/notifyAll()
注意:
Javaでは、各オブジェクトにオブジェクトロックフラグ(Object lock flag)が関連付けられており、スレッドAがオブジェクトのsynchronizedコードを呼び出すと、
まず、このオブジェクトに関連付けられたオブジェクトロックフラグを取得し、対応するコードを実行し、実行が終了したら、このオブジェクトロックフラグをオブジェクトに返します.したがって、スレッドAがsynchronizedコードを実行する間、別のスレッドBが同じオブジェクトのsynchronizedコードを実行する場合(スレッドAが実行するものとは限らない)、スレッドAが実行するまで待つことになる.
wait()notify()notifyAll()の利用方法
synchronizedコードが実行される間、スレッドはオブジェクトのwait()メソッドを呼び出し、オブジェクトロックフラグを解放し、待機状態に入り、notify()またはnotifyAll()メソッドを呼び出して待機中の他のスレッドを通知することができる.notify()は待機キュー内の最初のスレッドを通知し、notifyAll()は待機キュー内のすべてのスレッドを通知する

/**
*PrintNum.java
 * Created on 5:18:04 PM Feb 22, 2009
 *@author Quasar063501
 *@version 0.1
 * 
 */

public class PrintNum {
private byte[] lock = new byte[0];  //      ,      ,         this
public void demo() {
PrintThread a = new PrintThread("a");
PrintThread b = new PrintThread("b");
a.start();
b.start();
}

class PrintThread extends Thread {
public PrintThread(String name) {
this.setName(name);
}
public void run() {
synchronized(lock) {

for(int i =0; i < 100; i++) {

if(i % 10 == 0 && 0 != i) {

try {

lock.wait();   //      

lock.notify();       //        

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(this.getName()+": "+i);

}

}

}

}

}

                ,    !


    CSDN  ,       :http://blog.csdn.net/weizhaozhe/archive/2009/02/22/3922647.aspx

本文はCSDNブログから来て、転載して出典を明記してください:http://blog.csdn.net/weizhaozhe/archive/2009/02/22/3922647.aspx
Javaスレッドのスレッド同期
http://blog.csdn.net/mq612/archive/2007/03/04/1520583.aspx