Javaマルチスレッド/同時10、再ロック不可/スピンロック、再ロック可能
4323 ワード
ロックには、再ロック可能と再ロック不可があります.再入可能と再入不可の概念は、1つのスレッドが現在のインスタンスのロックを取得し、メソッドAに入り、このスレッドがこのロックを解放していないときに、再びメソッドAに入ることができるかどうかということである.再ロック可能:メソッドAに再アクセスすることができ、すなわち、ロックが解除される前に、このスレッドはメソッドAに再アクセスすることができる(メソッドA再帰). 再入ロック不可(スピンロック):再入メソッドA、すなわち、ロック入メソッドAを取得することは、このスレッドがロックマネーを解放する唯一の入メソッドAである.
まず、ロックの再入力性を例に挙げて説明します.
outerでinnerが呼び出され、outerは先にlockをロックし、innerはlockを取得できません.実際にouterを呼び出すスレッドはlockロックを取得していますが、innerで取得したロックリソースを再利用することはできません.このロックは再入力不可と呼ばれます.通常はスピンロックとも呼ばれます.対照的に、再読み込み可能とは、スレッドがすでに所有しているロックが同期しているコードブロックのいずれかに入ることを意味する.
isLockedがtrueに設定されると、スレッドがunlock()ロック解除を呼び出す前に、スレッドがロックを取得したかどうかにかかわらずwait()しか得られないことがわかります.コードは次のとおりです.
ロックを修正し、ロックされたスレッドを保存するために変数lockByを追加します.これにより、ロックされたスレッドをローにすることができます.
プログラムの2つの変数を説明します:lockBy:ロックインスタンスを取得したスレッドを保存し、lock()でロックを呼び出すスレッドが現在のロックインスタンスを取得したかどうかを判断し、ロックを取得した場合はwhileを直接スキップし、待つ必要はありません.lockCount:同じスレッドで1つのロックオブジェクトを繰り返しロックした回数を記録します.そうでなければ、このロックインスタンスが複数回ロックされている場合でも、unlockはすべてのロックを解除します.
Javaではsynchronizedとjava.util.concurrent.locks.ReentrantLockは再ロック可能です.
まず、ロックの再入力性を例に挙げて説明します.
public class UnReentrant{
Lock lock = new Lock();
public void outer(){
lock.lock();
inner();
lock.unlock();
}
public void inner(){
lock.lock();
//do something
lock.unlock();
}
}
outerでinnerが呼び出され、outerは先にlockをロックし、innerはlockを取得できません.実際にouterを呼び出すスレッドはlockロックを取得していますが、innerで取得したロックリソースを再利用することはできません.このロックは再入力不可と呼ばれます.通常はスピンロックとも呼ばれます.対照的に、再読み込み可能とは、スレッドがすでに所有しているロックが同期しているコードブロックのいずれかに入ることを意味する.
再ロック不可の基本原理:
isLockedがtrueに設定されると、スレッドがunlock()ロック解除を呼び出す前に、スレッドがロックを取得したかどうかにかかわらずwait()しか得られないことがわかります.コードは次のとおりです.
public class Lock{
private boolean isLocked = false;
public synchronized void lock()
throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify();
}
}
再入ロックの基本原理
ロックを修正し、ロックされたスレッドを保存するために変数lockByを追加します.これにより、ロックされたスレッドをローにすることができます.
public class Lock{
boolean isLocked = false;
Thread lockedBy = null;
int lockedCount = 0;
public synchronized void lock() throws InterruptedException{
Thread callingThread = Thread.currentThread();
while(isLocked && lockedBy != callingThread){
wait();
}
isLocked = true;
lockedCount++;
lockedBy = callingThread;
}
public synchronized void unlock(){
if(Thread.curentThread() == this.lockedBy){
lockedCount--;
if(lockedCount == 0){
isLocked = false;
notify();
}
}
}
}
プログラムの2つの変数を説明します:lockBy:ロックインスタンスを取得したスレッドを保存し、lock()でロックを呼び出すスレッドが現在のロックインスタンスを取得したかどうかを判断し、ロックを取得した場合はwhileを直接スキップし、待つ必要はありません.lockCount:同じスレッドで1つのロックオブジェクトを繰り返しロックした回数を記録します.そうでなければ、このロックインスタンスが複数回ロックされている場合でも、unlockはすべてのロックを解除します.
Javaではsynchronizedとjava.util.concurrent.locks.ReentrantLockは再ロック可能です.