Java 8 API学習25-java.util.concurrent.locks.Lock, ReentrantLock, Condition

3995 ワード

キーワードsynchronizedを用いるよりも、簡単に言えばロックの方がより具体的な動作が可能であるため、ある程度符号化を簡略化することができる.JavaドキュメントのLockインタフェースの説明を参照してください.
Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements
Lock
public interface Lock

このインタフェースはjavaで3つの実装があり、ReentrantLockとReentrantReadWriteLockである.ReadLockとReentrantReadWriteLock.WriteLock、後ろの2つはReentrantReadWriteLockの静的クラスです.上記の実装クラスを考慮するに、まずこのインタフェースで宣言する方法を見てみましょう.これらの方法はロックの実現クラスに不可欠な内容であることは明らかである.
void lock() //    ,      
//  ,          thread.interrupt()  ,       ,           
void lockInterruptibly() throws InterruptedException
void unlock()

boolean tryLock() //        ,       true,     false
boolean tryLock(long, TimeUnit) //      tryLock

Condition newCondition() //  3  

ReentrantLock
public class ReentrantLock implements Lock, java.io.Serializable

ReentrantLockの構造方法
ReentrantLock()
ReentrantLock(boolean)
ReentrantLock()ReentrantLock(false)に等価であり、非公平ロックが使用される.ReentrantLock(true)はフェアロックを使用する.フェアロックのメカニズムは簡単に言えばスレッドキューであり、要求待ち時間が最も長いスレッドにロックが割り当てられるが、このメカニズムはスケジューリングの公平性を保証することはできない(ロックの公平性については他の人の文章を参照してください).明らかに公平ロックの効率は非公平ロックより低い.フェアロックと非フェアロックはReentrantLockの2つの非publicの静的クラスであり、それぞれFairSyncとNonfairSyncと呼ばれている.
ReentrantLockのオブジェクトメソッド
ReentrantLockは再ロック可能という意味で、簡単に言えば同じスレッドが再び同期コードに入るときに、自分が取得したロックを使用することができる.実際にはsynchronizedも再入可能である.ロックインタフェースの宣言方法を実現する以外に、ReentrantLockはいくつかの方法を定義して、大部分の方法は再入可能な特性と関係がある.
//            
int getHoldCount() 
//             ;                            
final int getQueueLength() 
//    Condition       , *            
int getWaitQueueLength(Condition)

//              
boolean hasQueuedThread(Thread)
//             
final boolean hasQueuedThreads()
//         Condition     
boolean hasWaiters(Condition condition)

//      
final boolean isFair()
//         
boolean isHeldByCurrentThread()
//         
boolean isLocked()

まとめ
スレッドによるロックの取得は不確定であるため、getHoldCountを含む、上述の多くの方法では結果のリアルタイム性が保証されない.
Condition
ロックインタフェースでは、newConditionメソッドがConditionを返します.次に、このインタフェースの役割について説明します.
public interface Condition

複雑なマルチスレッド環境では、Conditionを使用することで問題をより明確に解決することができ、javaドキュメントでは「to give the effect of having multiple wait-sets per object,by combining them with the use of arbitrary Lock implementations」という.区別を容易にするために、Conditionにおける待機-起動の方法をそれぞれawaitsignalと呼ぶ.(ただし、Conditionの実装クラスはObjectにも引き継がれているため、waitnotifyの方法を用いることができるが、何の役にも立たない)ロックでは、newConditionを呼び出すたびに新しいConditionオブジェクトが生成する、明らかに異なるConditionは直接何の関係もない.Conditionで宣言する方法
//     ,     
void await() throws InterruptedException; 
/*     await,   void wait(timeout)  ,      ,   true, 
     ,   false*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
//  
boolean awaitUntil(Date deadline) throws InterruptedException;
//       ;            
long awaitNanos(long nanosTimeout) throws InterruptedException;

//    ,     
void awaitUninterruptibly() 

//     await  ,        
void signal()
//    await  
void signalAll()

IllegalMonitorStateException
Conditionのawaitおよびsignalの動作は、現在のスレッドがロックを取得する場合にのみ使用する必要がある、そうでないと、この異常が投げ出され、現在の状態ではConditionを操作できないことを示す.同様に、Object.waitおよびObject.notifysynchronizedの方法またはコードブロックで使用する、そうでなければ、この異常も放出される.
Conditionの実装クラス
呼び出しReentrantLock.lock.newConditon().getClass()のメソッドは、java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObjectの結果を返す、AbstractQueuedSynchronizerはpublicの抽象メソッドであるが、javaパケットにおいて、クラスは非publicである、この抽象クラスは、他の人が同期ロックまたはキューを実現するのを容易にするために使用される可能性がある.したがって、このクラスを説明する必要はない.