Java の最も基本的な同期方法は、synchronized キーワードを使用してメソッドへの同時アクセスを制御することです。 synchronized キーワードを使用して宣言されたすべてのメソッドはクリティカル セクションです。 Java では、同じオブジェクトのクリティカル セクションは 1 つだけ同時にアクセスできます。
静的メソッドの動作は異なります。 synchronized キーワードを使用して宣言された静的メソッドには、同時に 1 つの実行スレッドのみがアクセスできますが、他のスレッドはこのオブジェクトの非静的 synchronized メソッドにアクセスできます。 2 つのスレッドがオブジェクトの 2 つの異なる同期メソッドに同時にアクセスできるため、この点には細心の注意が必要です。つまり、一方は静的同期メソッド、もう一方は非静的同期メソッドです。両方の方法で同じデータを変更すると、データ不整合エラーが発生します。
synchronized ブロックの構文は次のとおりです:
public void method() { synchronized(表达式) { } }
synchronized キーワードには 2 つの用途があります。1 つはメソッドの定義でのみ使用され、もう 1 つは synchronized を使用してオブジェクトを同期するだけではありません。変数を使用することもできます。synchronizedl を使用して、クラス内の静的メソッドと非静的メソッドを同期することもできます。
最初のメソッド: 非静的メソッドの同期
関連する Java 文法から、synchronized キーワードを使用してメソッドを定義すると、クラス内の静的メソッドと synchroniezd キーワードを使用して定義された非静的メソッドがロックされることがわかります。しかし、これは少し悪いです。同期ブロックでそのような効果を実現したい場合、クラス内のすべての同期された非静的メソッドをロックするために synchronized を使用する場合、この効果が発生する理由を理解するのは難しくありません。これを synchronized ブロックのパラメーターとして使用するには、synchronized ブロックのコードは次のようになります。
public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } } public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } }
上記のコードでは、method1 は synchronized ブロックを使用し、method2 メソッドは synchronized キーワードを使用してメソッドを定義します。同じ Test インスタンスが使用されている場合、これら 2 つのメソッドのいずれかが実行中である限り、同期ロックが取得されないため、他のメソッドはブロックされます。これを同期ブロックのパラメーターとして使用することに加えて、Test.this を同期ブロックのパラメーターとして使用して、同じ効果を実現することもできます。
内部クラスで同期ブロックを使用する場合、これは内部クラスのみを表し、外部クラス (OuterClass) とは関係ありません。ただし、内部クラスの非静的メソッドと外部クラスの非静的メソッドも同期できます。内部クラスにメソッド method3 を追加すると、Test の 2 つのメソッドと同期することもできます。 コードは次のとおりです。
public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } } public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } }
上記の InnerClass のメソッド 3 と、Test のメソッド 1 とメソッド 2 は 1 つだけ持つことができます。メソッドも同時に実行されます。
同期ブロックが正しく実行された場合でも、プログラムエラーによる例外で同期ブロックを終了した場合でも、現在の同期ブロックが保持している同期ロックは自動的に解放されるため、同期ブロックの問題を心配する必要はありません。同期ブロックを使用します。
2. 静的メソッドの同期
静的メソッドの呼び出し時にオブジェクトインスタンスが作成されるとは限らないため、これを使用して静的メソッドを同期することはできませんが、静的メソッドを同期するには Class オブジェクトを使用する必要があります。コードは次のとおりです。
public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } } public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } }
静的メソッドを同期する場合、クラスの静的フィールド クラスを使用してクラス オブジェクトを取得できます。上記の例では、method1 メソッドとmethod2 メソッドには、実行するメソッドが 1 つだけあります。クラス フィールドを使用してクラス オブジェクトを取得することもできます。インスタンスの getClass() メソッドでクラス オブジェクトを取得します。コードは次のとおりです。
public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } } public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } }
上記のコードでは、パブリック静的オブジェクトを通じて Test のインスタンスを取得します。を取得し、このインスタンスの getClass メソッドを通じてクラス オブジェクトを取得します (すべてのクラスのインスタンスが getClass メソッドを通じて同じ Class オブジェクトを取得することに注意してください)。クラスを介してさまざまなクラスの静的メソッドを同期することもできます。コードは次のとおりです。
public class Test1{ public static void method1(){ synchronized(Test.class){ } } } public class Test1{ public static void method1(){ synchronized(Test.class){ } } }
注: 同期ブロックを使用してメソッドを同期する場合、非静的メソッドはこれを通じて同期できますが、静的メソッドはクラス オブジェクトを使用して同期する必要があります。 , ただし、クラスを使用して非静的メソッドを静的メソッドと同期することもできます。ただし、これを静的メソッドで使用して非静的メソッドを同期することはできません。同期ブロックを使用する場合は、この点に注意する必要があります。
注
synchronized キーワードはアプリケーションのパフォーマンスを低下させるため、共有データを変更する必要があるメソッドの同時シナリオでのみ使用する必要があります。複数のスレッドが同じ同期メソッドにアクセスする場合、1 つのスレッドのみがそれにアクセスでき、他のスレッドは待機します。メソッド宣言で synchronized キーワードを使用しない場合、すべてのスレッドがメソッドを同時に実行できるため、合計実行時間が短縮されます。メソッドが複数のスレッドによって呼び出されないことがわかっている場合、synchronized キーワードを使用してメソッドを宣言する必要はありません。
同期済みとして宣言されたメソッドは再帰的に呼び出すことができます。スレッドがオブジェクトの同期メソッドにアクセスすると、このメソッドへのアクセスを再度取得することなく、実行中のメソッドを含むオブジェクトの他の同期メソッドを呼び出すこともできます。
我们可以通过synchronized关键字来保护代码块(而不是整个方法)的访问。应该这样利用synchronized关键字:方法的其余部分保持在synchronized代码块之外,以获取更好的性能。临界区(即同一时间只能被一个线程访问的代码块)的访问应该尽可能的短。例如在获取一幢楼人数的操作中,我们只使用synchronized关键字来保护对人数更新的指令,并让其他操作不使用共享数据。当这样使用synchronized关键字时,必须把对象引用作为传入参数。同一时间只有一个线程被允许访问这个synchronized代码。通常来说,我们使用this关键字来引用正在执行的方法所属的对象:
synchronized(this){ //Java code }
更多Java中synchronized关键字修饰方法同步的用法详解相关文章请关注PHP中文网!