Synchronizedは、C ++で記述されたアトミックな組み込みロックです。内部のソースコードは表示されません。これは一連の命令です。この命令を使用して、オブジェクトのロック操作を実装できます。
構文:(1)同期コードブロック;(2)同期メソッド。
オブジェクトロック(モニター)メカニズム:
(1)まず、同期を使用して同期されたコードブロックのロック操作を観察しましょう。
package Synchronized;
public class SynchronizedTest {
public static Object object=new Object();
public static void main(String[] args) {
synchronized (object){
System.out.println("hello baby");
}
}
}
分解後、分解されたエンコーディング情報を確認できます。
同期コードブロックを実行した後、monitorenter命令を最初に実行し、終了時にmonitorexit命令を実行する必要があります。分析後、同期にSynchronizedを使用するための鍵は、オブジェクトのモニターモニターを取得することであることがわかります。スレッドがモニターを取得した後は、実行を続行できます。それ以外の場合は、待機することしかできません。取得プロセスは相互に排他的です。つまり、同時にモニターを取得できるのは1つのスレッドだけです。
上記のバイトコードには、monitorenter命令と2つのmonitorexit命令が含まれています。これは、Java仮想マシンが、取得したロックを通常の実行パスと異常な実行パスの両方でロック解除できるようにする必要があるためです。
(2)同期コードブロックのロックとコンパイルを実行した後:
このマークは、コンパイルされたバイトコードファイルACC_SYNCHRONIZEDに表示されます。これは、メソッドに入るとき、およびJava仮想マシンがmonitorenter操作を実行する必要があることを示します。このとき、正常に戻っているか、呼び出し元に例外をスローしているかにかかわらず、Java仮想マシンはmonitorexit操作を実行する必要があります。(したがって、2つのmonitorexit出口操作があります)
public class SynchronizedTest {
public static Object object=new Object();
public synchronized void eat(){
System.out.println("eat banana");
}
public static void main(String[] args) {
SynchronizedTest s=new SynchronizedTest();
s.eat();
}
}
コンパイルされた結果は次のとおりです。
monitorenterとmonitorexitの役割:
各ロックオブジェクトには、ロックカウンターと、ロックを保持しているスレッドへのポインターがあることを抽象的に理解できます。
monitorenterの実行時に、ターゲットロックオブジェクトのカウンタが0の場合、他のスレッドによって保持されていないことを意味します。この場合、Java仮想マシンは、ロックオブジェクトの保持スレッドを現在のスレッドとして設定し、そのカウンターを1インクリメントします。ターゲットロックオブジェクトのカウンターが0でない場合、ロックオブジェクトを保持しているスレッドが現在のスレッドである場合、Java仮想マシンはカウンターを1増やすことができます。それ以外の場合は、保持しているスレッドがロックを解放するまで待機する必要があります。 。
monitorexitが実行されると、Java仮想マシンはロックオブジェクトのカウンターを1デクリメントする必要があります。カウンタが0に減少すると、ロックが解除されたことを意味します。
このカウンターメソッドを使用する理由は、同じスレッドが同じロックを繰り返し取得できるようにするためです。たとえば、Javaクラスに複数の同期されたメソッドがある場合、これらのメソッド間の相互呼び出しには、直接的または間接的を問わず、同じロックに対して繰り返しロック操作が含まれます。したがって、プログラミングでの暗黙の制約を回避するために、このようなリエントラント機能を設計する必要があります。