マルチスレッド-スレッド同期ロック-ロックロック-ReentrantLock
スレッド同期メカニズムの同期ロックについては前述しましたが、実際には、スレッド同期を実現できるJUCロックロックもあります。さらに、Lock実装クラスReentrantLockは、Synchronizeよりも柔軟性があり、豊富であり、ほとんどのシナリオでの使用に適しています。
ReentrantLockとSynchronizeを簡単に比較してみましょう。
- 同期ロックは排他ロックです。キーワード同期またはコードブロックが追加されている限り、ロックとロックの解除は自動的に行われます。使い方はとても簡単ですが、柔軟性は劣ります。ReentrantLockも排他的ロックですが、手動ロック(ロックなど)とロック解除(ロック解除)が必要です。使用は比較的複雑ですが、柔軟性があり、ReentrantLockは豊富なメソッドを提供します。
- SynchronsizeとReentrantLockはどちらも再入可能ロックです(ロックは複数回使用できます。たとえば、メソッドAはロックを使用しますが、実際にはBを呼び出しますが、Bもロックを使用します。つまり、呼び出すときにロックを再取得する必要はありません。 B)。ただし、他のスレッドがロックを取得できるようにするには、すべてがロックを解放する必要があります。
- Synchronizeがロックを取得できず、デッドロック待機状態が生成されると、対応するものを中断することはできず、ReentrantLockは対応するミッドオーダーロックを提供します。
- 最も重要なことは、ReentrantLockがフェアロックメカニズムも実装できることです。フェアロックとは何ですか?つまり、ロックで最も長く待機したスレッドは、ロックを使用する権利を取得します。一般的な理解では、最も長いキューにいる人は誰でも最初にロックを取得します。
Synchronizeとは異なり、ReentrantLockは、さまざまなニーズに応じてスレッド同期の問題を処理できる複数のロックを提供します。以下では、ReentrantLockロックに焦点を当てます。Synchronizeの概要については、前のブログThread Insecurity + Thread Deadlock + Synchronizationを確認してください。
ReentrantLockは、ロックインターフェイスを実装するJUCパッケージ(java.util.concurrent.locks.ReentrantLock)のクラスです。
ReentrantLockリリースロックはすべて同じロック解除方法です。以下では、主にReentrantLockのさまざまなロックについて説明します。
スレッド同期が実装されていない場合、ロック効果はありません。
public class ReenTrantLockThread {
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
new Thread(threadTest,"小明").start();
new Thread(threadTest,"小王").start();
}
}
class ThreadTest implements Runnable{
final Lock lock = new ReentrantLock();
@Override
public void run() {
study();
}
public void study(){
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":我正在学习");
}
}
}
結果:
XiaoMingとXiaoWangは怒って、CPUスケジューリングによって学習しました。ロックを追加した後、1人が学習を終了すると、次のスレッドがロックを取得して学習します(次のスレッドは必ずしも別の人である必要はなく、CPUによってスケジュールされます)
(1)Lock()このロックは、同期ロックと同様に、一般的で一般的に使用されるロックです。ロックを取得したら、ロックを保持し続ける前に、ロックが解放されるのを待つ必要があります。そうしないと、スレッドのデッドロックが発生します。発生するため、使用終了後にロックを解除する必要があります。
注:ロックが解除されないようにするには、通常、ロックの内容を試してから、最後にロックを解除して、ロックが確実に解除されるようにします。
public void study(){
lock.lock();
try { /
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":我正在学习");
}
}catch (Exception e){
}finally {
lock.unlock()
}
}
結果:1人の人に学習を終了させてから、次のスレッドのロックで学習させます!!!
(2)tryLock()ロック。これをtryロックと呼びます。ロックの取得を試みるために使用されます。取得できる場合は、ロックを占有して使用できます。使用できない場合は、他のロックも処理できます。物事。戻り値があり、型はブール値です。ロックを取得するとtrueを返し、取得できない場合はfalseを返すため、何があってもすぐに値を返します。
public void study(){
boolean flag = lock.tryLock();
if(flag){
try {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":我正在学习");
}
}catch (Exception e){
}finally {
lock.unlock();
}
}else {
System.out.println(Thread.currentThread().getName()+":我没拿到锁,那我去看电视了");
}
}
結果:
(3)tryLock(long timeout、TimeUnit unit)、使用法はtryLockと同じですが、待機時間を指定できる点が異なります。つまり、後でロックが取得されない場合は、ロックしてロックを保持します。指定された時間、私はfalseを返します、時間その前に、私はロックが解放されるのを待ち続けました。
public void study() throws InterruptedException {
boolean flag = lock.tryLock(5000,TimeUnit.MILLISECONDS); // 等待5秒钟拿不到锁就返回false
if(flag){
try {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":我正在学习");
}
}catch (Exception e){
}finally {
lock.unlock();
}
}else {
System.out.println(Thread.currentThread().getName()+":我没拿到锁,那我去看电视了");
}
}
結果:ロックは5秒以内に正常に取得されました。
スレッドにスリープを追加し、スレッドを5秒以上休止させます。
(4)lockInterruptibly()割り込みロック。このロックを使用して、Thread.interrupt()を使用してスレッドをアクティブに割り込みます。このスレッドはロックを使用することを前提としており、ロックなしでは使用できません。これを示すのは簡単ではありません。使用法は次のとおりです。
次に、ReentrantLockの特別なロックメカニズムであるフェアロックとアンフェアロックについて説明します。
文字通りの意味と同じように、
フェアロックとは、どのスレッドが長時間キューに入れられるかによって、誰でもスケジュールを組むことができることを意味します。
不公平なロックとは、スレッドがいつキューに入れ始めても、CPUにムードスケジュールを確認させることを意味します。
使用方法は非常に単純で、ロックを初期化するときにtrue(公正)またはfalse(不公正)パラメーターを追加するだけで済みます。デフォルトはfalse
フェアロックです。
final Lock lock = new ReentrantLock(true);
public void study() throws InterruptedException {
for (int i = 0; i <2 ; i++) {
try {
lock.lock(); // 等待5秒钟拿不到锁就返回false
System.out.println(Thread.currentThread().getName()+":我正在学习");
//Thread.sleep(2000);
}catch (Exception e){
}finally {
lock.unlock();
}
}
}
結果:絞らないでください、誰もがシェアを持っています。
不当なロック:
final Lock lock = new ReentrantLock(false);
public void study() throws InterruptedException {
for (int i = 0; i <2 ; i++) {
try {
lock.lock(); // 等待5秒钟拿不到锁就返回false
System.out.println(Thread.currentThread().getName()+":我正在学习");
//Thread.sleep(2000);
}catch (Exception e){
}finally {
lock.unlock();
}
}
}
結果:次の
映画の紹介:読み取り/書き込みロック。