Java並発注のロックとCondition条件
10744 ワード
一、Synchronized
synchronizedはJavaのキーワードであり、Java言語に内蔵されている特性である.一つのコードブロックがsynchronizedに修飾されている場合、一つのスレッドが対応するロックを取得し、コードブロックを実行すると、他のスレッドはずっと待つしかない.ロックを取得するスレッドがロックを解放するのを待つが、ロックを取得するスレッドがロックを解放するのは3つの場合がある.ロックを取得したスレッドはコードブロックを実行し、スレッドはロックの占有を解放します.2.スレッド実行に異常が発生した場合、JVMはスレッドに自動的にロックを解除させる.3.waitメソッドを呼び出し、待っている間にすぐにロックを解除し、他のスレッドがロックを使用するのを便利にする.
二、ロックロック LockはJava言語に組み込まれていません. synchronizedはJVMレベルで実現されており、コード実行に異常が発生した場合、JVMは自動的にロックを解放するが、ロックはだめで、ロックが必ず解放されることを保証するには、unLockをfinally{}に入れなければならない(手動解放). リソース競合が激しくない場合、SynchronizedのパフォーマンスはReetarntLockよりも優れていますが、激しい場合、synchronizedのパフォーマンスは数十倍低下します. ReentrantLockはロックを追加しました: void lock();//無条件のロック. void lockInterruptibly throws InterruptedException;//割り込み可能なロック. boolean tryLock();//ロックを取得したらすぐにtrueに戻り、他のスレッドが持っている場合はfalseに戻り、待つことはありません. boolean tryLock(long timeout,TimeUnit unit);//ロックが取得されるとすぐにtrueが返され、他のスレッドがロックを持っている場合、パラメータが与えられた時間が待機し、待機中にロックが取得されるとtrueが返され、待機タイムアウトが発生した場合falseが返されます.
ReentrantLockを使用してロックを取得したらすぐに戻り、ロックを取得していない場合、現在のスレッドはスリープ状態にあり、ロックを取得するまで、または現在のスレッドが他のスレッドによって中断されて他のことをすることができる.ただしsynchronizedであれば、ロックが取得されなければ待ち続けます.
三、Condition条件 Conditionのawait()メソッドはObjectのwait()メソッドに相当し、Conditionのsignal()メソッドはObjectのnotify()メソッドに相当し、ConditionのsignalAll()はObjectのnotifyAll()メソッドに相当する.異なることに、Objectのこれらの方法は同期ロックとバンドルされて使用される.Conditionは、反発ロック/共有ロックとバンドルして使用する必要があります. Conditionより強力な点は、マルチスレッドのスリープと起動をより細かく制御できることです.同じロックの場合、異なる状況で異なるConditionを使用する複数のConditionを作成できます.
例えば、マルチスレッドが同じバッファを読み書きする場合、バッファにデータを書き込むと、「リードスレッド」が起動する.バッファからデータを読み出すと、「書き込みスレッド」が起動する.バッファがいっぱいになると、「書き込みスレッド」は待つ必要があります.バッファが空の場合、「リードスレッド」は待機する必要があります.
Objectクラスのwait()、notify()、notifyAll()を使用してバッファを実装する場合、バッファにデータを書き込んだ後に「リードスレッド」を起動する必要がある場合、notify()またはnotifyAll()で明確に指定された「リードスレッド」を起動することはできませんが、notifyAllを通じてすべてのスレッドを起動するしかありません(ただし、notifyAllでは起動したスレッドがリードスレッドなのか、ライトスレッドなのかは区別できません).しかし,Conditionにより,起動リードスレッドを明確に指定できる.
synchronizedはJavaのキーワードであり、Java言語に内蔵されている特性である.一つのコードブロックがsynchronizedに修飾されている場合、一つのスレッドが対応するロックを取得し、コードブロックを実行すると、他のスレッドはずっと待つしかない.ロックを取得するスレッドがロックを解放するのを待つが、ロックを取得するスレッドがロックを解放するのは3つの場合がある.ロックを取得したスレッドはコードブロックを実行し、スレッドはロックの占有を解放します.2.スレッド実行に異常が発生した場合、JVMはスレッドに自動的にロックを解除させる.3.waitメソッドを呼び出し、待っている間にすぐにロックを解除し、他のスレッドがロックを使用するのを便利にする.
二、ロックロック
三、Condition条件
例えば、マルチスレッドが同じバッファを読み書きする場合、バッファにデータを書き込むと、「リードスレッド」が起動する.バッファからデータを読み出すと、「書き込みスレッド」が起動する.バッファがいっぱいになると、「書き込みスレッド」は待つ必要があります.バッファが空の場合、「リードスレッド」は待機する必要があります.
Objectクラスのwait()、notify()、notifyAll()を使用してバッファを実装する場合、バッファにデータを書き込んだ後に「リードスレッド」を起動する必要がある場合、notify()またはnotifyAll()で明確に指定された「リードスレッド」を起動することはできませんが、notifyAllを通じてすべてのスレッドを起動するしかありません(ただし、notifyAllでは起動したスレッドがリードスレッドなのか、ライトスレッドなのかは区別できません).しかし,Conditionにより,起動リードスレッドを明確に指定できる.
package com.imooc.locks;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Task {
private final Lock lock = new ReentrantLock();
private final Condition addCondition = lock.newCondition();
private final Condition subCondition = lock.newCondition();
private static int num = 0;
private List lists = new LinkedList();
public void add() {
lock.lock();
try {
while(lists.size() == 10) {// , " "
addCondition.await();
}
num++;
lists.add("add Banana" + num);
System.out.println("The Lists Size is " + lists.size());
System.out.println("The Current Thread is " + Thread.currentThread().getName());
System.out.println("==============================");
this.subCondition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {//
lock.unlock();
}
}
public void sub() {
lock.lock();
try {
while(lists.size() == 0) {// ," "
subCondition.await();
}
String str = lists.get(0);
lists.remove(0);
System.out.println("The Token Banana is [" + str + "]");
System.out.println("The Current Thread is " + Thread.currentThread().getName());
System.out.println("==============================");
num--;
addCondition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package com.imooc.locks;
public class AddThread implements Runnable {
private Task task;
public AddThread(Task task) {
this.task = task;
}
@Override
public void run() {
task.add();
}
}
package com.imooc.locks;
public class SubThread implements Runnable {
private Task task;
public SubThread(Task task) {
this.task = task;
}
@Override
public void run() {
task.sub();
}
}
package com.imooc.locks;
public class TestLock {
public static void main(String[] args) {
Task task = new Task();
Thread t1=new Thread(new AddThread(task));
Thread t3=new Thread(new AddThread(task));
Thread t7=new Thread(new AddThread(task));
Thread t8=new Thread(new AddThread(task));
Thread t2 = new Thread(new SubThread(task));
Thread t4 = new Thread(new SubThread(task));
Thread t5 = new Thread(new SubThread(task));
Thread t6 = new Thread(new SubThread(task));
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
}
}