この記事では、Java マルチスレッドのキーワード volatile、lock、synchronized について簡単に紹介します。必要な方は参考にしていただければ幸いです。 。
1. 揮発性
揮発性書き込みと揮発性読み取りのメモリ セマンティクス:
スレッド A は揮発性変数を書き込みます。これは本質的にスレッド A によるメモリへの書き込みです。この揮発性変数のスレッドがメッセージを発行しました (共有変数が変更されました)。スレッド B が volatile 変数を読み取るとき、本質的に、スレッド B は前のスレッドによって送信されたメッセージ (volatile 変数を書き込む前の共有変数への変更) を受信します。スレッド A が揮発性変数を書き込み、次にスレッド B がその揮発性変数を読み取ります。このプロセスは基本的に、スレッド A がメイン メモリを介してスレッド B にメッセージを送信します。
ロック解放とロック取得のメモリ セマンティクス:
スレッド A はロックを解放します。本質的に、スレッド A は次にロックを取得するスレッドにメッセージを送信します (スレッド A は変数を共有します)。修正)メッセージ。スレッド B はロックを取得します。本質的に、スレッド B は前のスレッド (ロックを解放する前に共有変数を変更した) によって送信されたメッセージを受信します。スレッド A がロックを解放し、次にスレッド B がロックを取得します。このプロセスは基本的に、スレッド A がメイン メモリを介してスレッド B にメッセージを送信します。
概要: volatile キーワードの役割は、変数を複数のスレッド間で可視化することですが、volatile だけではスレッドの安全性を保証できません。
2. lock
Lock はインターフェイスです:
public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); }
lock()、tryLock()、tryLock(long time, TimeUnit 単位)、lockInterruptibly() は次の目的で使用されます。ロックを取得します。
unLock() メソッドはロックを解放するために使用されます。 tryLock() メソッドには戻り値があり、取得が成功した場合 (つまり、ロックが別のスレッドによって取得された場合) に true を返します。 false を返します。これは、このメソッドが何があってもすぐに返されることを意味します。ロックができないときにそこで待つ必要はありません。 tryLock(long time, TimeUnit単位)メソッドはtryLock()メソッドと似ていますが、時間内にロックを取得できない場合は一定時間待機する点が異なります。制限がある場合は false を返します。ロックが最初に取得された場合、または待機中に取得された場合は true を返します。 lockInterruptibly() メソッドは特別で、このメソッドを通じてロックを取得する場合、スレッドがロックの取得を待機している場合、スレッドは割り込みに応答できます。つまり、スレッドの待機状態を中断できます。つまり、2 つのスレッドが同時に lock.lockInterruptibly() を通じてロックを取得したいとき、この時点でスレッド A がロックを取得し、スレッド B が待機しているだけであれば、 threadB.interrupt() メソッドは次のようになります。スレッド B で呼び出されます。スレッド B の待機中のプロセスに割り込むことができます。
ロックは、ロックの取得プロセス中に中断される可能性があります。 lock はロックの取得を試みることができます。ロックが別のスレッドによって保持されている場合は false を返し、現在のスレッドをスリープさせません。 lock がロックを取得しようとすると、時間パラメータが渡されます。この時間範囲内にロックが取得されなかった場合、リクエストは終了します。 synchronized は自動的にロックを解除しますが、lock は自動的にロックを解除しません。注: lock() はコードの一部をロックするために使用できるため、ロックが解放されるまで他のコードは待機する必要があります。lock は同期のように自動的にロックを解放しないので、 try-finally をブロックし、ロックが確実に解放されるようにします。
Lock と synchronized には次の違いがあります。
1) Lock はインターフェースですが、synchronized は Java のキーワードであり、synchronized は組み込み言語の実装です。 # 2) 例外が発生すると、synchronized はスレッドによって占有されているロックを自動的に解放するため、デッドロックは発生しませんが、例外が発生したときに、Lock が unLock() を通じてロックを積極的に解放しないと、デッドロックが発生する可能性があります。デッドロックが発生するため、Lock を使用する場合は、finally ブロックでロックを解放する必要があります。
3) Lock を使用すると、ロックを待機しているスレッドが割り込みに応答できるようになりますが、synchronized を使用する場合はそれができません。 synchronized では、待機中のスレッドは永遠に待機し、割り込みに応答できません。
4) Lock を通じて、ロックが正常に取得されたかどうかを知ることができますが、synchronized ではこれを行うことはできません。
5) ロックにより、複数スレッドの読み取り操作の効率が向上します。パフォーマンスの点では、リソースの競合が激しくない場合、リソースの競合が非常に激しい (つまり、同時に多数のスレッドが競合している) 場合、両者のパフォーマンスはほぼ同じになります。 Lock のパフォーマンスは、synchronized のパフォーマンスよりもはるかに優れています。したがって、使用する場合には適切な状況に応じて選択する必要があります。 ReentrantLock は「再入可能なロック」を意味します。リエントラント ロックの概念については、次のセクションで説明します。 ReentrantLock は Lock インターフェイスを実装する唯一のクラスであり、ReentrantLock はさらに多くのメソッドを提供します。
3. synchronized
1. 2 つの同時スレッドが同じオブジェクト内の同期された (この) 同期コード ブロックにアクセスする場合、一度に 1 つのスレッドのみを実行できます。別のスレッドは、このコード ブロックを実行する前に、現在のスレッドがこのコード ブロックの実行を完了するまで待つ必要があります。
2. ただし、スレッドがオブジェクトの同期された (この) 同期コード ブロックにアクセスするとき、別のスレッドは引き続きオブジェクト内の非同期 (この) 同期コード ブロックにアクセスできます。
3. 特に重要なのは、スレッドがオブジェクトの同期された (この) 同期されたコード ブロックにアクセスすると、オブジェクト内の他のすべての同期された (この) 同期されたコード ブロックへの他のスレッドのアクセスがブロックされることです。
4. 3 番目の例は、他の同期コード ブロックにも適用できます。つまり、スレッドがオブジェクトの synchronized (this) 同期コード ブロックにアクセスすると、このオブジェクトのオブジェクト ロックを取得します。その結果、オブジェクト オブジェクトのすべての同期されたコード部分への他のスレッドのアクセスが一時的にブロックされます。 synchronized キーワードの範囲: オブジェクト インスタンス内で、synchronized aMethod(){} を使用すると、複数のスレッドがこのオブジェクトの synchronized メソッドに同時にアクセスすることを防ぐことができます (オブジェクトに複数の同期メソッドがある場合、1 つのスレッドがそのうちの 1 つにアクセスする限り)同期メソッド メソッドにアクセスすると、他のスレッドはこのオブジェクトの同期メソッドに同時にアクセスできなくなります)。現時点では、異なるオブジェクト インスタンスの同期メソッドは相互に干渉しません。つまり、他のスレッドは同じクラスの別のオブジェクト インスタンスの同期メソッドに同時にアクセスできます。特定のクラスのスコープ内では、同期静的 aStaticMethod{} により、複数のスレッドがこのクラスの同期静的メソッドにアクセスできなくなります。同時に。これは、クラスのすべてのオブジェクト インスタンスに対して機能します。
以上がJava マルチスレッドのキーワード volatile、lock、synchronized の簡単な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。