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. デッドロック問題
##相互排他的な条件
一定期間内リソースは 1 つのスレッドによってのみ占有されます。このとき、他のスレッドがリソースを要求した場合、要求元のスレッドは待つことしかできません。
#非剥奪条件
スレッドによって取得されたリソースは、スレッドが取得する前に他の人が使用することはできません。スレッドが強制的にそれを奪った場合、そのリソースを解放できるのは、そのリソースを取得したスレッドだけです (能動的にのみ解放できます)。
スレッドは少なくとも 1 つのリソースを保持していますが、新しいリソース要求を行っています。 、リソースはすでに他のスレッドによって占有されています。この時点で、要求元のスレッドはブロックされますが、取得したリソースは保持されます。
デッドロックが発生した場合、プロセス待ちキュー{P1、P2、 &hellip ;,Pn}、P1 は P2 が占有するリソースを待ち、P2 は P3 が占有するリソースを待ち、...、Pn は P1 が占有するリソースを待ち、プロセス待機ループを形成します。ループ内の各プロセスは別のプロセスによって同時に占有され、アプリケーションとは、前のプロセスが後のプロセスが所有するリソースを占有することを意味します。 3. synchronized の制限
プログラムで
キーワードを使用し、デッドロックが発生した場合、synchronized の鍵となるのは、「譲渡不可能な」デッドロックを破壊できないことです。ロック条件。これは、リソースに対して同期を適用する場合、適用できない場合はスレッドが直接ブロック状態になるためで、スレッドがブロック状態になると何もできず、スレッドが占有しているリソースを解放することもできません。
しかし、ほとんどのシナリオでは、「不可侵」の状態が破壊されることを望んでいます。つまり、「非剥奪」の条件に対して、あるリソースを占有しているスレッドがさらに他のリソースを申請する際、適用できない場合には、占有しているリソースを積極的に解放することができるため、「非剥奪」の条件は満たされます。剥奪」は破壊される。
同期問題を解決するために自分でロックを再設計する場合、どのように設計すればよいでしょうか?
(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 サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック

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

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

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

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

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