synchronizedの原理とwait/notifyとの絡み合い
3738 ワード
説明:みんながObjectのモニタに依存するため、多かれ少なかれ相互影響
一、synchronized原理:
マルチスレッドの場合、各スレッドはプロセスのリソースを共有し、データの一貫性を保証するためにjavaはsynchronizedを導入します.3つの方法:1.synchronized method 2.synchronized code block 3.static synchronized method
1.synchronized method:
このとき
methodの実行が見られると、method 1が待機している.これはsynchronized methodがオブジェクトロックを行い、現在のオブジェクトのmonitorをロックし、各オブジェクトにmonitorのロックがあり、初期状態は0であり、synchronizedの値が1になるからである.このとき、他のスレッドがこのコードにアクセスすると、
まず、このオブジェクトのモニタが0であるかどうかを検出します.
1.0であればそのまま占有し、モニタを1に変更
2.この値が1の場合、スレッドは、他の占有者がこのロックを解放するまで待機します.
2.synchronized code block同理.
3.static synchronized methodは静的手法であるため,このクラスをロックしている.このクラスに対するすべての静的同期方法は,上記の競合メカニズムが同じオブジェクトに限定されないことを行う.
二、wait/notify
Objectクラスのオブジェクトには、次のいくつかのnativeメソッドがあります.
wait()/notify()はmonitorのスレッドを取得する必要があります.詳細はObjectのソースコード注記を参照してください.
三、wait/notifyの絡み合い
もつれ1
waitを実行するにはmonitorを取得する必要がありますが、第1部ではsynchronized methodについて説明します.waitメソッドを実行するにはsynchronizedと混合して使用する必要があります.そうしないと、IllegalMonitorStateException例外が放出されます.
もつれ2
このときマルチスレッド実行objを開くmethodメソッドを実行する.次のことがわかります.
1.これらのスレッドはwait状態に入っています.
賢いあなたは疑問を発見したかどうか疑問に思っています:synchronized methodは、この方法がmonitorを取得して実行できることを示しています.スレッド1がmonitorを取得して待機状態に入った以上、他のスレッドが彼を呼び覚ますことがない場合、同期コードブロックの内部で、このとき他のスレッドはブロックされているはずです.
2.waitがmonitorを解放したため
waitが起動するには他のスレッドnotifyが必要であり、notifyを実行するにはmonitorオブジェクトロックも必要であるため、waitがこのロックを解放しない場合、notifyが現在のスレッドを起動するためにmonitorを取得できるスレッドはありません.
まとめ:
wait,notifyはsynchronizedコードブロックで実行する必要があり,waitはまたこの同期を破壊する.
一、synchronized原理:
マルチスレッドの場合、各スレッドはプロセスのリソースを共有し、データの一貫性を保証するためにjavaはsynchronizedを導入します.3つの方法:1.synchronized method 2.synchronized code block 3.static synchronized method
1.synchronized method:
public class SyncObj {
public synchronized void method() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("method run");
}
public synchronized void method1() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("method1 run");
}
}
このとき
public static void main(String[] args) {
final SyncObj obj=new SyncObj();
new Thread(){
@Override
public void run() {
obj.method();
}
}.start();
new Thread(){
@Override
public void run() {
obj.method1();
}
}.start();
}
methodの実行が見られると、method 1が待機している.これはsynchronized methodがオブジェクトロックを行い、現在のオブジェクトのmonitorをロックし、各オブジェクトにmonitorのロックがあり、初期状態は0であり、synchronizedの値が1になるからである.このとき、他のスレッドがこのコードにアクセスすると、
まず、このオブジェクトのモニタが0であるかどうかを検出します.
1.0であればそのまま占有し、モニタを1に変更
2.この値が1の場合、スレッドは、他の占有者がこのロックを解放するまで待機します.
2.synchronized code block同理.
3.static synchronized methodは静的手法であるため,このクラスをロックしている.このクラスに対するすべての静的同期方法は,上記の競合メカニズムが同じオブジェクトに限定されないことを行う.
二、wait/notify
Objectクラスのオブジェクトには、次のいくつかのnativeメソッドがあります.
//wait
/**
* This method should only be called by a thread that is the owner
* of this object's monitor.
*/
public final native void wait() throws InterruptedException;
public final native void wait(long millis, int nanos) throws InterruptedException;
public final void wait(long millis) throws InterruptedException {
wait(millis, 0);
}
//notify
/**
* Wakes up a single thread that is waiting on this object's
* monitor. If any threads are waiting on this object, one of them
* is chosen to be awakened. The choice is arbitrary and occurs at
* the discretion of the implementation. A thread waits on an object's
* monitor by calling one of the {@code wait} methods.
*/
public final native void notify();
/**
* Wakes up all threads that are waiting on this object's monitor. A
* thread waits on an object's monitor by calling one of the
* {@code wait} methods.
*/
public final native void notifyAll();
wait()/notify()はmonitorのスレッドを取得する必要があります.詳細はObjectのソースコード注記を参照してください.
三、wait/notifyの絡み合い
/**
* This method should only be called by a thread that is the owner
* of this object's monitor.
*/
もつれ1
waitを実行するにはmonitorを取得する必要がありますが、第1部ではsynchronized methodについて説明します.waitメソッドを実行するにはsynchronizedと混合して使用する必要があります.そうしないと、IllegalMonitorStateException例外が放出されます.
public synchronized void method() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("method run");
}
もつれ2
このときマルチスレッド実行objを開くmethodメソッドを実行する.次のことがわかります.
1.これらのスレッドはwait状態に入っています.
賢いあなたは疑問を発見したかどうか疑問に思っています:synchronized methodは、この方法がmonitorを取得して実行できることを示しています.スレッド1がmonitorを取得して待機状態に入った以上、他のスレッドが彼を呼び覚ますことがない場合、同期コードブロックの内部で、このとき他のスレッドはブロックされているはずです.
2.waitがmonitorを解放したため
waitが起動するには他のスレッドnotifyが必要であり、notifyを実行するにはmonitorオブジェクトロックも必要であるため、waitがこのロックを解放しない場合、notifyが現在のスレッドを起動するためにmonitorを取得できるスレッドはありません.
まとめ:
wait,notifyはsynchronizedコードブロックで実行する必要があり,waitはまたこの同期を破壊する.