ホームページ > Java > &#&チュートリアル > Java のロックとは何ですか? Java のロックの詳細な紹介

Java のロックとは何ですか? Java のロックの詳細な紹介

不言
リリース: 2018-09-27 17:16:34
オリジナル
10378 人が閲覧しました

この記事の内容は、Java のロックとは何ですか? Java におけるロックの詳細な紹介は、参考になると思います。

1. はじめに

ロックは、Synchronized キーワードと 関連を使用して Java に実装されます。 java.util.concurrent パッケージの下のクラス。

ロックを実装するために Java によって提供される関連 API:

Java のロックとは何ですか? Java のロックの詳細な紹介

Lock が提供するものSynchronized 同期メソッドや同期ステートメント ブロックを使用するよりも幅広いロック操作が可能です。

#2.java.util.concurrent パッケージ

ロック インターフェイス

//试图获取锁.
void lock() 
 
//如果当前线程未被中断,则获取锁.
void lockInterruptibly()
         
//返回绑定到此 Lock 实例的新 Condition 实例.
Condition newCondition()
          
//仅在调用时锁为空闲状态才获取该锁.
boolean tryLock()
          
//如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁.
boolean tryLock(long time, TimeUnit unit)
          
//试图释放锁.
void unlock()
ログイン後にコピー

ReentranLock クラス

構築方法

//创建一个 ReentrantLock 的实例.
ReentrantLock()          
//创建一个具有给定公平策略的 ReentrantLock实例.
ReentrantLock(boolean fair)
ログイン後にコピー

フェアロック: マルチスレッドはロックを申請した順にロックを取得します。

不公平なロック: マルチスレッドは、ロックを適用した順序でロックを取得しません。つまり、最初にロックを適用したスレッドが、必ずしも最初にロックを適用するとは限りません。ロックを取得します。

#一般的なメソッドの概要

//试图获取锁.   void lock() //如果当前线程未被中断,则获取锁.void lockInterruptibly() //仅在调用时锁未被另一个线程保持的情况下,才获取该锁.boolean tryLock() //如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁.  boolean tryLock(long timeout, TimeUnit unit) //试图释放此锁.    void unlock() //返回用来与此 Lock 实例一起使用的 Condition 实例.Condition newCondition() //如果此锁的公平设置为 true,则返回 true.boolean isFair() //返回正等待获取此锁的线程估计数.int getQueueLength()     //返回等待与此锁相关的给定条件的线程估计数.int getWaitQueueLength(Condition condition) //返回标识此锁及其锁定状态的字符串.String  toString()
ログイン後にコピー

条件インターフェイス

//使当前线程在接收到信号前或被中断前一直保持等待状态.
void await()
          
//使当前线程在接收到信号前或被中断前或达到指定时间前一直保持等待状态(TimeUnit为时间单位).
boolean await(long time, TimeUnit unit)
          
//使当前线程在接收到信号前或被中断前或达到指定时间前一直保持等待状态(单位为毫秒).
long awaitNanos(long nanosTimeout)
 
//使当前线程在接收到信号前或被中断前或达到最后日期期限前一直保持等待状态.
boolean awaitUntil(Date deadline)
 
//唤醒一个在该Condition实例等待的线程.
void signal()
 
//唤醒所有在该Condition实例等待的线程.         
void signalAll()
ログイン後にコピー

#Condition インスタンスは、Lock インスタンスの条件コントロールとして Lock インスタンスにバインドされます。

Condition インターフェイスによって宣言されたメソッドを呼び出す前に、まずこの Condition に関連するロックを取得する必要があります。

メソッド await()、await(long time, TimeUnit Unit)、awaitNanos(long nanosTimeout)、awaitUntil(Date Deadline) が呼び出された後、これは条件関連のロックはアトミックに解放されます。

signal() メソッドと signalAll() メソッドが呼び出された後、目覚めたスレッドは await() メソッドから戻る前にロックを再取得する必要があります。 #使用例:

#

/**
* @Auther: ZHUANGHAOTANG
* @Date: 2018/9/26 17:36
* @Description:
*/
public class TestReentranLock implements Runnable{

    /**
     * 可重入锁
     */
    private ReentrantLock reentrantLock = new ReentrantLock(true);

    /**
     * 锁条件
     */
    private Condition condition = reentrantLock.newCondition();

    /**
     * 业务处理
     */
    public void service(){
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName+":尝试获取锁");
        reentrantLock.lock();
        System.out.println(threadName+":获取锁成功");
        try {
            System.out.println(threadName+":使当前线程等待,并释放锁资源。");
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            reentrantLock.unlock();
            System.out.println(threadName+":释放锁");
        }
    }

    /**
     * 唤醒在该Condition实例等待的线程
     */
    public void signalAll(){
        reentrantLock.lock();
        condition.signalAll();
        reentrantLock.unlock();
    }

    @Override
    public void run() {
        service();
    }

    public static void main(String[] args) {

        TestReentranLock testReentranLock = new TestReentranLock();

        Thread threadA = new Thread(testReentranLock,"线程A");
        Thread threadB = new Thread(testReentranLock,"线程B");
        Thread threadC = new Thread(testReentranLock,"线程C");

        threadA.start();
        threadB.start();
        threadC.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        testReentranLock.signalAll();

    }

}
ログイン後にコピー
#フェアロック実行結果: #
线程B:尝试获取锁
线程A:尝试获取锁
线程B:获取锁成功
线程C:尝试获取锁
线程B:使当前线程等待,并释放锁资源。
线程A:获取锁成功
线程A:使当前线程等待,并释放锁资源。
线程C:获取锁成功
线程C:使当前线程等待,并释放锁资源。
线程B:释放锁
线程C:释放锁
线程A:释放锁
ログイン後にコピー

不公平なロックの実行結果:

线程B:尝试获取锁
线程A:尝试获取锁
线程A:获取锁成功
线程C:尝试获取锁
线程A:使当前线程等待,并释放锁资源。
线程C:获取锁成功
线程C:使当前线程等待,并释放锁资源。
线程B:获取锁成功
线程B:使当前线程等待,并释放锁资源。
线程A:释放锁
线程B:释放锁
线程C:释放锁
ログイン後にコピー

ReadWriteLock インターフェイス

//返回用于读取操作的锁.
Lock readLock()          
//返回用于写入操作的锁.
Lock writeLock()
ログイン後にコピー
ReentrantReadWriteLock クラス

構築方法

//创建一个ReentrantReadWriteLock实例.
ReentrantReadWriteLock()        
//创建一个具有给定公平策略的ReentrantReadWriteLock实例.
ReentrantReadWriteLock(boolean fair)
ログイン後にコピー

共通メソッドの概要

//返回用于读取操作的锁.
Lock ReentrantReadWriteLock。ReadLock。readLock()   
//返回用于写入操作的锁.
Lock ReentrantReadWriteLock。WriteLock。writeLock()
//返回等待获取读取或写入锁的线程估计数目.
int getQueueLength()
//如果此锁的公平设置为 true,则返回 true.
boolean isFair()
//返回标识此锁及其锁状态的字符串.
String toString()
ログイン後にコピー

ReadLock/WriteLock 静的内部クラス共通メソッドの概要

//试图获取锁.
void lock() 
//如果当前线程未被中断,则获取锁.
void lockInterruptibly()
          
//返回绑定到此 Lock 实例的新 Condition 实例.
Condition newCondition()
          
//仅在调用时锁为空闲状态才获取该锁.
boolean tryLock()
          
//如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁.
boolean tryLock(long time, TimeUnit unit)
          
//试图释放锁.
void unlock()
 
//返回标识此锁及其锁状态的字符串.
String toString()
ログイン後にコピー

ReadLock は条件をサポートしていないため、ReadLock が呼び出されるとき、 newCondition() メソッドは UnsupportedOperationException 例外をスローします。

ReentrantReadWriteLock を使用した読み取りロックと書き込みロックは、読み取りと読み取りの共有、書き込みと書き込みの相互排他、および読み取りと書き込みの相互排他に従います。

使用例:

/**
* @Auther: ZHUANGHAOTANG
* @Date: 2018/9/26 18:04
* @Description:
*/
public class TestReentrantReadWriteLock implements Runnable{


    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true);

    /**
     * 读锁
     */
    private Lock readLock = reentrantReadWriteLock.readLock();

    /**
     * 写锁
     */
    private Lock writeLock = reentrantReadWriteLock.writeLock();

    /**
     * 读取操作
     */
    public void reading(){
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName+":尝试获取读锁");
        readLock.lock();
        System.out.println(threadName+":获取读锁成功");
        System.out.println(threadName+":释放读锁");
        readLock.unlock();
    }

    /**
     * 写入操作
     */
    public void writing(){
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName+":尝试获取写锁");
        writeLock.lock();
        System.out.println(threadName+":获取写锁成功");
        System.out.println(threadName+":释放写锁");
        writeLock.unlock();
    }


    public static void main(String[] args) {
        TestReentrantReadWriteLock testReentrantReadWriteLock = new TestReentrantReadWriteLock();

        Thread threadA = new Thread(testReentrantReadWriteLock,"线程A");
        Thread threadB = new Thread(testReentrantReadWriteLock,"线程B");
        Thread threadC = new Thread(testReentrantReadWriteLock,"线程C");

        threadA.start();
        threadB.start();
        threadC.start();
    }

}
ログイン後にコピー

共有実行結果の読み取り:

@Overridepublic void run() {     
 //读读共享      
 reading();
}
ログイン後にコピー
线程A:尝试获取读锁
线程B:尝试获取读锁
线程A:获取读锁成功
线程A:释放读锁
线程C:尝试获取读锁
线程C:获取读锁成功
线程C:释放读锁
线程B:获取读锁成功
线程B:释放读锁
ログイン後にコピー

読み取りロックは複数のスレッドで同時に取得できるため、読み取りの効率が向上します (ただし、読み取りロックのみが取得されている場合は解放する必要はありません)使用すると、書き込みロックの取得に影響します))

書き込み-書き込み相互排他実行結果:

@Overridepublic void run() {  
    //写写互斥     
    writing();
}
ログイン後にコピー
线程A:尝试获取写锁
线程B:尝试获取写锁
线程A:获取写锁成功
线程C:尝试获取写锁
线程A:释放写锁
线程B:获取写锁成功
线程B:释放写锁
线程C:获取写锁成功
线程C:释放写锁
ログイン後にコピー

書き込みロックは同時にのみロックできます。スレッドによって取得できます。

相互排除の読み取りと書き込みの実行結果:

@Overridepublic void run() {      
   //读写互斥      
   writing();
  reading();
}
ログイン後にコピー
线程A:尝试获取写锁
线程C:尝试获取写锁
线程B:尝试获取写锁
线程A:获取写锁成功
线程A:释放写锁
线程A:尝试获取读锁
线程C:获取写锁成功
线程C:释放写锁
线程C:尝试获取读锁
线程B:获取写锁成功
线程B:释放写锁
线程B:尝试获取读锁
线程C:获取读锁成功
线程C:释放读锁
线程A:获取读锁成功
线程A:释放读锁
线程B:获取读锁成功
线程B:释放读锁
ログイン後にコピー

読み取り中は書き込みできません。書き込み中、つまり読み取りロックを取得するとき、書き込みロックが現在スレッドによって保持されている場合、読み取りはできません。書き込みロックを取得するとき、読み取りロックが現在保持されている場合は、書き込みロックが解放されるまで待機します。スレッドによって、読み取りロックが解放されるまで待機することになりますが、書き込みロックは保持されません。

3. Java におけるロックの分類

Java におけるロックは次のとおりです。ロックを特性ごとに分けます。

#公平なロック/不公平なロック

公平なロック: ロックにはマルチスレッドが適用されます。に従って順番にロックを取得します。

不公平なロック: マルチスレッドは、ロックを適用する順序でロックを取得しません。つまり、最初の lock() を持つスレッドが最初にロックを取得するわけではありません。ロック。

ReentranLock ロックと ReentrantReadWriteLock ロックの場合、構築メソッドによって公平なロックか不公平なロックかを設定できます。

#Synchronized キーワードの場合、これは不当なロックです。

共有ロック/排他ロック

共有ロック: ReadLock の場合、複数のスレッドが同時にロックを保持できることを意味します。それは共有ロックです。

排他ロック: ReentranLock、WriteLock、および Synchronized の場合、ロックは同時に 1 つのスレッドによってのみ保持できることを意味します。

#楽観的ロック/悲観的ロック

楽観的ロックと悲観的ロックは特定のロックではありません特性だけでなく、同時実行性を見るときの視点。

オプティミスティック ロック: 同時操作はデータの整合性に影響を与えないと考えられているため、ロックする必要はありません。

悲観的ロック: 同時操作はデータの整合性に確実に影響を与えると考えられるため、ロックを実行する必要があります。

読み取り操作はオプティミスティック ロックに適しています。つまり、ロックが実行されないため、データの読み取り効率が向上します。

書き込み操作は悲観的ロックに適しています。つまり、ロックを実行する必要があります。

セグメント化ロック

セグメント化ロックとは、ロックの粒度を調整することで同時操作を制御するロックの設計を指します。 . 、Java の ConcurrentHashMap のセグメントは、セグメント ロックの設計を通じて同時操作を実装します。

バイアス ロック/軽量ロック/重量ロック

バイアス ロック、軽量ロック、重量ロックはすべてフィンガー ロックです。同期されたキーワード。

バイアス ロック: 同期されたメソッドまたは同期されたステートメント ブロックが常に 1 つのスレッドによってのみ保持されることを意味します。このとき、ロック ステータスはバイアス ロックとなり、コストが削減されます。ロックを取得しているスレッド。

軽量ロック: ロック ステータスがバイアス ロックの場合、他のスレッドからアクセスされると、他のスレッドはスピンによってロックを取得しようとします。ステータスは軽量ロックです。

Spin は、一定回数ループしてロックを取得しようとします。このメソッドの欠点は、CPU パフォーマンスを消費しないことです。

ヘビーウェイト ロック: ロック ステータスが軽量ロックの場合、スピン後に他のスレッドがロックを取得していない場合、ロック ステータスはヘビーウェイト ロックになります。この時点では、その他です。スレッドはブロック状態になり、パフォーマンスが低下します。

#ロック状態が偏ったロックの場合、パフォーマンスは最も高く、ロックが重い場合、パフォーマンスは最も低くなります。

以上がJava のロックとは何ですか? Java のロックの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート