目次
synchronized
しかし、ほとんどのシナリオでは、「不可侵」の状態が破壊されることを望んでいます。つまり、「非剥奪」の条件に対して、あるリソースを占有しているスレッドがさらに他のリソースを申請する際、適用できない場合には、占有しているリソースを積極的に解放することができるため、「非剥奪」の条件は満たされます。剥奪」は破壊される。
(1) 割り込みに応答する機能。
ホームページ Java &#&チュートリアル Java では、synchronized キーワードを使用するだけでなく、Lock を提供する必要があるのはなぜですか?

Java では、synchronized キーワードを使用するだけでなく、Lock を提供する必要があるのはなぜですか?

Apr 20, 2023 pm 05:01 PM
java synchronized lock

概要: synchronized キーワードは、1 つのスレッドのみが同期されたコード ブロックにアクセスできるようにするために Java で提供されています。 synchronized キーワードが提供されているのに、なぜ Lock インターフェースも Java SDK パッケージで提供されるのですか?これは不必要な車輪の再発明でしょうか?今日はこの問題について一緒に話し合います。

synchronized キーワードは、1 つのスレッドのみが同期されたコード ブロックにアクセスできるようにするために、Java で提供されています。 synchronized キーワードが提供されているのに、なぜ Lock インターフェースも Java SDK パッケージで提供されるのですか?これは不必要な車輪の再発明でしょうか?今日はこの問題について一緒に話し合います。 #########質問?

JVM には synchronized キーワードが提供されており、1 つのスレッドだけが同期されたコード ブロックにアクセスできるようになっているのに、なぜ Lock インターフェイスを提供する必要があるのでしょうか。これは車輪の再発明なのでしょうか?なぜ Java 設計者はこのようなことを行うのでしょうか?質問とともに下を見ていきましょう。

1. なぜ Lock インターフェースを提供するのでしょうか?

多くの友人は、Java 1.5 バージョンでは synchronized のパフォーマンスが Lock ほど良くなかったと聞いたことがあるかもしれませんが、Java 1.6 バージョン以降、

synchronized

は多くの最適化を行い、パフォーマンスが向上しました。かなり改善されましたが、ほとんど改善されませんでした。同期キーワードのパフォーマンスが向上しているのに、なぜ依然として Lock を使用するのでしょうか?

さらに深く考えると、考えるのは難しくありません。synchronized

を使用してロックを行う場合、積極的にロックを解放することはできず、デッドロックの問題が発生します。

2. デッドロック問題

デッドロックが発生する場合、以下の 4 つの必要条件が存在する必要があり、いずれも必須ではありません。

Java では、synchronized キーワードを使用するだけでなく、Lock を提供する必要があるのはなぜですか?##相互排他的な条件

  • 一定期間内リソースは 1 つのスレッドによってのみ占有されます。このとき、他のスレッドがリソースを要求した場合、要求元のスレッドは待つことしかできません。

#非剥奪条件

  • スレッドによって取得されたリソースは、スレッドが取得する前に他の人が使用することはできません。スレッドが強制的にそれを奪った場合、そのリソースを解放できるのは、そのリソースを取得したスレッドだけです (能動的にのみ解放できます)。

要求と保持の条件

  • スレッドは少なくとも 1 つのリソースを保持していますが、新しいリソース要求を行っています。 、リソースはすでに他のスレッドによって占有されています。この時点で、要求元のスレッドはブロックされますが、取得したリソースは保持されます。

ループ待ち条件

  • デッドロックが発生した場合、プロセス待ちキュー{P1、P2、 &hellip ;,Pn}、P1 は P2 が占有するリソースを待ち、P2 は P3 が占有するリソースを待ち、...、Pn は P1 が占有するリソースを待ち、プロセス待機ループを形成します。ループ内の各プロセスは別のプロセスによって同時に占有され、アプリケーションとは、前のプロセスが後のプロセスが所有するリソースを占有することを意味します。 3. synchronized の制限

  • プログラムで
synchronized

キーワードを使用し、デッドロックが発生した場合、synchronized の鍵となるのは、「譲渡不可能な」デッドロックを破壊できないことです。ロック条件。これは、リソースに対して同期を適用する場合、適用できない場合はスレッドが直接ブロック状態になるためで、スレッドがブロック状態になると何もできず、スレッドが占有しているリソースを解放することもできません。

しかし、ほとんどのシナリオでは、「不可侵」の状態が破壊されることを望んでいます。つまり、「非剥奪」の条件に対して、あるリソースを占有しているスレッドがさらに他のリソースを申請する際、適用できない場合には、占有しているリソースを積極的に解放することができるため、「非剥奪」の条件は満たされます。剥奪」は破壊される。

同期問題を解決するために自分でロックを再設計する場合、どのように設計すればよいでしょうか?

4. 問題を解決する

同期の制限を理解した後、同期ロックを自分で実装できる場合、どのように設計すればよいでしょうか?言い換えれば、ロックを設計するときに同期の制限をどのように解決すればよいでしょうか?ここで、この問題は3つの側面から考えることができると思います。

(1) 割り込みに応答する機能。

synchronized

の問題は、ロック A を保持した後、ロック B の取得に失敗すると、スレッドがブロックされた状態になることです。デッドロックが発生すると、ブロックされたスレッドをウェイクアップする機会がなくなります。 。しかし、ブロックされたスレッドが割り込み信号に応答できる場合、つまり、ブロックされたスレッドに割り込み信号を送信したときにスレッドをウェイクアップできる場合、スレッドは一度保持していたロック A を解放する機会が得られます。これは不可侵条件に違反します。

(2) タイムアウトをサポートします。スレッドが一定期間内にロックを取得できず、ブロック状態に入る代わりにエラーを返した場合、スレッドは一度保持していたロックを解放する機会もあります。これはまた、不可侵の条件を損なうことになる。

(3) ノンブロッキングでロックを取得します。ロックの取得に失敗し、ブロッキング状態にならずに直接戻った場合、スレッドは一度保持していたロックを解放する機会もあります。これはまた、不可侵の条件を損なうことになる。

は、Lock インターフェースで提供される 3 つのメソッドである Lock インターフェースに反映されます。

は次のとおりです:

// 支持中断的API
void lockInterruptibly() throws InterruptedException;
// 支持超时的API
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 支持非阻塞获取锁的API
boolean tryLock();
ログイン後にコピー
  • lockInterruptibly()

は割り込みをサポートします。

  • tryLock() メソッド

tryLock() メソッドには戻り値があり、ロックの取得を試みるために使用されることを意味します。取得が成功した場合は true を返し、取得が失敗した場合 (つまり、ロックが別のスレッドによって取得された場合) は false を返します。これは、このメソッドは何があってもすぐに戻ることを意味します。ロックができないときにそこで待つ必要はありません。

  • tryLock(長時間、TimeUnit 単位) メソッド

tryLock(長時間、TimeUnit 単位) メソッドと tryLock () メソッドも似ていますが、ロックが取得できない場合は一定時間待機し、制限時間内にロックを取得できない場合は false を返す点が異なります。ロックが最初に取得された場合、または待機中に取得された場合は true を返します。

言い換えれば、デッドロック問題の場合、Lock は譲渡不可能な状態を破壊できます。たとえば、以下のプログラム コードはデッドロックの譲渡不可能な状態を破壊します。

public class TansferAccount{
    private Lock thisLock = new ReentrantLock();
    private Lock targetLock = new ReentrantLock();
    //账户的余额
    private Integer balance;
    //转账操作
    public void transfer(TansferAccount target, Integer transferMoney){
        boolean isThisLock = thisLock.tryLock();
        if(isThisLock){
            try{
                boolean isTargetLock = targetLock.tryLock();
                if(isTargetLock){
                    try{
                         if(this.balance >= transferMoney){
                            this.balance -= transferMoney;
                            target.balance += transferMoney;
                        }   
                    }finally{
                        targetLock.unlock
                    }
                }
            }finally{
                thisLock.unlock();
            }
        }
    }
}
ログイン後にコピー

例外として、Lock の下に ReentrantLock があり、ReentrantLock は公正なロックと不公平なロックをサポートします。

ReentrantLock を使用する場合、ReentrantLock には 2 つのコンストラクターがあり、1 つはパラメーターなしのコンストラクター、もう 1 つは Fair パラメーターを渡すコンストラクターです。 Fair パラメータは、ロックの公平性戦略を表します。true が渡された場合は、公平なロックを構築する必要があることを意味し、それ以外の場合は、不公平なロックを構築する必要があることを意味します。これを次のコード スニペットに示します。

//无参构造函数: 默认非公平锁
public ReentrantLock() {
	sync = new NonfairSync();
} 
//根据公平策略参数创建锁
public ReentrantLock(boolean fair){
	sync = fair ? new FairSync() : new NonfairSync();
}
ログイン後にコピー

ロックの実装は基本的にエントリ待ちキューに対応します。スレッドがロックを取得できない場合、スレッドは待機キューに入ります。スレッドがロックを解放するときは、待機状態からウェイクアップする必要があります。キュー、待機中のスレッド。公平なロックの場合、ウェイクアップ戦略は長時間待機した人をウェイクアップすることであり、これは非常に公平です。不公平なロックの場合、この公平性の保証は提供されず、待機時間の短いスレッドが優先されます。先に目覚めるかもしれない。 Lock は公平なロックをサポートしますが、同期は公平なロックをサポートしません。

最後に、Lock を使用してロックする場合は、たとえば次のコード スニペットに示すように、finally{} コード ブロックでロックを解放する必要があることに注意してください。

try{
    lock.lock();
}finally{
    lock.unlock();
}
ログイン後にコピー

注: 同期とロックのその他の詳細な説明については、友達が自分で確認できます。

以上がJava では、synchronized キーワードを使用するだけでなく、Lock を提供する必要があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

See all articles