Java 5 以降、java.util.concurrent.locks パッケージにはいくつかのロック実装が含まれているため、独自のロックを実装する必要はありません。ただし、これらのロックの使用方法を理解する必要があります。
単純なロック
Java の synchronized ブロックから始めましょう:
public class Counter{ private int count = 0; public int inc(){ synchronized(this){ return ++count; } } }
inc() メソッドに synchronized(this) コード ブロックがあることがわかります。このコード ブロックは、同時に 1 つのスレッドだけが return ++count を実行できることを保証します。 synchronized 同期ブロック内のコードはより複雑になる可能性がありますが、スレッド同期の意味を表現するには ++count のような単純な操作で十分です。
次の Counter クラスは、同じ目的を達成するために同期の代わりに Lock を使用します:
public class Counter{ private Lock lock = new Lock(); private int count = 0; public int inc(){ lock.lock(); int newCount = ++count; lock.unlock(); return newCount; } }
lock() メソッドは Lock インスタンス オブジェクトをロックするため、オブジェクトの lock() メソッドを呼び出すすべてのスレッドは、ロックが完了するまでブロックされます。 Lock オブジェクトの lock() メソッドが呼び出されます。
Lock クラスの簡単な実装を次に示します。
public class Counter{ public class Lock{ private boolean isLocked = false; public synchronized void lock() throws InterruptedException{ while(isLocked){ wait(); } isLocked = true; } public synchronized void unlock(){ isLocked = false; notify(); } }
「スピン ロック」とも呼ばれる while(isLocked) ループに注目してください。 isLocked が true の場合、lock() を呼び出すスレッドは wait() 呼び出しの待機をブロックします。スレッドが notify() 呼び出しを受信せずに wait() から戻ること (誤ったウェイクアップとも呼ばれます) を防ぐために、スレッドは isLocked 条件を再チェックして、実行を継続しても安全かどうか、または実行を継続しても安全かどうかを判断します。再度待機する必要があり、スレッドが目覚めた後も安全に実行を継続できるとは考えられません。 isLocked が false の場合、現在のスレッドは while(isLocked) ループを終了し、isLocked を true に戻し、lock() メソッドを呼び出している他のスレッドが Lock インスタンスをロックできるようにします。
スレッドがクリティカルセクション(lock()とunlock()の間)のコードを完了すると、unlock()が呼び出されます。 lock() を実行すると、isLocked が false にリセットされ、lock() メソッドの wait() 関数の呼び出し後に待機状態になっていたスレッド (存在する場合) の 1 つが通知 (ウェイクアップ) されます。
ロックの再入可能
Java の同期ブロックは再入可能です。これは、Java スレッドがコード内の同期された同期ブロックに入り、その同期ブロックで使用される同期オブジェクトに対応するモニターのロックを取得した場合、このスレッドは同じモニター オブジェクトによって同期された別のブロックに入ることができることを意味します。 Javaコード。以下に例を示します。
public class Reentrant{ public synchronized outer(){ inner(); } public synchronized inner(){ //do something } }
outer() と inner() の両方が synchronized として宣言されていることに注意してください。これは、Java の synchronized(this) ブロックに相当します。スレッドが external() を呼び出す場合、両方のメソッド (コードのブロック) が同じモニター オブジェクト (「this」) によって同期されるため、outer() 内で inner() を呼び出しても問題はありません。スレッドがすでにモニター オブジェクトのロックを所有している場合、スレッドはモニター オブジェクトによって同期されたすべてのコード ブロックにアクセスできます。これがリエントランシーです。スレッドは、すでに所有しているロックによって同期されているコードの任意のブロックに入ることができます。
前に示したロックの実装は再入可能ではありません。 Reentrantクラスを以下のように書き換えると、スレッドがouter()を呼び出すと、inner()メソッドのlock.lock()でブロックされてしまいます。
public class Reentrant2{ Lock lock = new Lock(); public outer(){ lock.lock(); inner(); lock.unlock(); } public synchronized inner(){ lock.lock(); //do something lock.unlock(); } }
outer() を呼び出すスレッドは、まず Lock インスタンスをロックし、次に inner() を呼び出し続けます。 inner() メソッドでは、スレッドは Lock インスタンスを再度ロックしようとしますが、Lock インスタンスは既に external() メソッドでロックされているため、アクションは失敗します (つまり、スレッドはブロックされます)。
2 つの lock() 呼び出しの間に lock() が呼び出されないと、lock() の実装を確認すると、その理由が明らかになることがわかります:
public class Lock{ boolean isLocked = false; public synchronized void lock() throws InterruptedException{ while(isLocked){ wait(); } isLocked = true; } ... }
スレッドが許可されているかどうか。 lock() を終了する方法は、while ループ (スピン ロック) 内の条件によって決まります。現在の判定条件は、どのスレッドがロックしたかに関係なく、isLocked が false の場合にのみロック操作が許可されます。
この Lock クラスを再入可能にするには、それに小さな変更を加える必要があります:
public class Lock{ boolean isLocked = false; Thread lockedBy = null; int lockedCount = 0; public synchronized void lock() throws InterruptedException{ Thread callingThread = Thread.currentThread(); while(isLocked && lockedBy != callingThread){ wait(); } isLocked = true; lockedCount++; lockedBy = callingThread; } public synchronized void unlock(){ if(Thread.curentThread() == this.lockedBy){ lockedCount--; if(lockedCount == 0){ isLocked = false; notify(); } } } ... }
while ループ (スピン ロック) が、Lock インスタンスをロックしたスレッドも考慮するようになったことに注意してください。現在のロック オブジェクトがロックされていない (isLocked = false)、または現在の呼び出しスレッドが既に Lock インスタンスをロックしている場合、while ループは実行されず、lock() を呼び出しているスレッドはメソッドを終了できます (翻訳注:現在のセマンティクスでは、「このメソッドの終了が許可される」ということは、wait() が呼び出されず、ブロッキングが発生しないことを意味します。
さらに、同じスレッドがロック オブジェクトを繰り返しロックした回数を記録する必要があります。それ以外の場合は、現在のロックが複数回ロックされている場合でも、1 回の unblock() 呼び出しでロック全体がロック解除されます。対応する lock() 呼び出しの数に unlock() 呼び出しが達する前にロックが解放されることは望ましくありません。
これで、この Lock クラスは再入可能になりました。
ロックの公平性
Java の同期ブロックは、ブロックに入ろうとするスレッドの順序を保証しません。したがって、複数のスレッドが同じ同期ブロックへのアクセスを求めて常に競合する場合、そのうちの 1 つまたは複数のスレッドがアクセスを取得できない危険性があります。つまり、アクセスは常に他のスレッドに割り当てられることになります。この状況はスレッドの飢餓と呼ばれます。この問題を回避するには、ロックが公平である必要があります。この記事で紹介されているロックは、同期されたブロックを使用して内部で実装されているため、公平性は保証されません。
在 finally 语句中调用 unlock()
如果用 Lock 来保护临界区,并且临界区有可能会抛出异常,那么在 finally 语句中调用 unlock()就显得非常重要了。这样可以保证这个锁对象可以被解锁以便其它线程能继续对其加锁。以下是一个示例:
lock.lock(); try{ //do critical section code, //which may throw exception } finally { lock.unlock(); }
这个简单的结构可以保证当临界区抛出异常时 Lock 对象可以被解锁。如果不是在 finally 语句中调用的 unlock(),当临界区抛出异常时,Lock 对象将永远停留在被锁住的状态,这会导致其它所有在该 Lock 对象上调用 lock()的线程一直阻塞。
以上就是关于 java 多线程锁的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!
更多java 多线程-锁详解及示例代码相关文章请关注PHP中文网!

この記事では、2025年の上位4つのJavaScriptフレームワーク(React、Angular、Vue、Svelte)を分析し、パフォーマンス、スケーラビリティ、将来の見通しを比較します。 強力なコミュニティと生態系のためにすべてが支配的なままですが、彼らの相対的なポップ

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

この記事では、リモートコードの実行を可能にする重大な欠陥であるSnakeyamlのCVE-2022-1471の脆弱性について説明します。 Snakeyaml 1.33以降のSpring Bootアプリケーションをアップグレードする方法は、このリスクを軽減する方法を詳述し、その依存関係のアップデートを強調しています

node.js 20は、V8エンジンの改善、特により速いガベージコレクションとI/Oを介してパフォーマンスを大幅に向上させます。 新機能には、より良いWebセンブリのサポートと洗練されたデバッグツール、開発者の生産性とアプリケーション速度の向上が含まれます。

大規模な分析データセットのオープンテーブル形式であるIcebergは、データの湖のパフォーマンスとスケーラビリティを向上させます。 内部メタデータ管理を通じて、寄木細工/ORCの制限に対処し、効率的なスキーマの進化、タイムトラベル、同時wを可能にします

この記事では、Lambda式、Streams API、メソッド参照、およびオプションを使用して、機能プログラミングをJavaに統合することを調べます。 それは、簡潔さと不変性を通じてコードの読みやすさと保守性の改善などの利点を強調しています

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

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

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境
