Java での synchronized の使い方のまとめ
1.関数修飾子として synchronized を使用する場合のサンプルコードは次のとおりです:
Public synchronized void method(){ //…. }
これが同期メソッドですが、このときどのオブジェクトが同期ロックされているのでしょうか?彼がロックするのは、この同期されたメソッド オブジェクトを呼び出すことです。言い換えれば、オブジェクト P1 がこの同期メソッドを異なるスレッドで実行すると、同期効果を達成するために相互排他が形成されます。ただし、このオブジェクトが属するクラスが生成する別のオブジェクトP2は、synchronizedキーワードを付加してこのメソッドを任意に呼び出すことができる。
上記のサンプル コードは、次のコードと同等です:
public void method() { synchronized (this) // (1) { //….. } }
(1) のこれは何を指しますか?彼は、このメソッドを呼び出すオブジェクト (P1 など) を指します。同期メソッドの本質は、オブジェクト参照に synchronized を適用することであることがわかります。 ——P1 オブジェクト ロックを取得したスレッドのみが P1 の同期メソッドを呼び出すことができます。P2 に関する限り、P1 ロックはそれとは何の関係もありません。プログラムは同期メカニズムの制御を取り除くこともできますこの場合、データの混乱が生じます。
2.同期ブロックのサンプル コードは次のとおりです。
public void method(SomeObject so) { synchronized(so) { //….. } }
現時点では、ロックは so オブジェクトであり、ロックを取得した人は誰でも、自分が制御するコードを実行できます。ロックとしてクリアなオブジェクトがある場合は、次のようにプログラムを書くことができますが、ロックとしてクリアなオブジェクトがなく、コードの一部を同期したいだけの場合は、特別なインスタンス変数を作成できます (オブジェクト) をロックとして機能させるには:
class Foo implements Runnable { private byte[] lock = new byte[0]; // 特别的instance变量 Public void method() { synchronized(lock) { //… } } //….. }
注: 長さ 0 のバイト配列オブジェクトは、どのオブジェクトよりも作成する方が経済的です - コンパイルされたバイトコードを確認してください: 長さ 0 の byte[] オブジェクトを生成するには、次のことが必要です。オペコードは 3 つだけですが、Object lock = new Object() には 7 行のオペコードが必要です。
3.静的関数に同期を適用します。サンプル コードは次のとおりです:
Class Foo { public synchronized static void method1() // 同步的static 函数 { //…. } public void method2() { synchronized(Foo.class) // class literal(类名称字面常量) } }
コード内のメソッド 2() メソッドは、クラス リテラルをロックとして使用します。同期された静的関数で生成される効果同様に、取得されるロックは非常に特殊で、現在このメソッドを呼び出しているオブジェクトが属するクラス (このクラスによって生成された特定のオブジェクトではなく、クラス) です。
「Effective Java」という本で、同期ロックに Foo.class と P1.getClass() を使用することは同じではないということを見た記憶があります。このクラスをロックする目的を達成するために P1.getClass() を使用することはできません。 。 P1 は、Foo クラスによって生成されたオブジェクトを参照します。
推論できます: 同期静的関数 A がクラスで定義され、同期インスタンス関数 B も定義されている場合、このクラスの同じオブジェクト Obj が複数のスレッドでそれぞれ A メソッドと B メソッドにアクセスすると、ロックが異なるため、同期は行われません。メソッド A のロックは Obj が属するクラスであり、メソッド B のロックは Obj が属するオブジェクトです。
Java での synchronized の使用方法の概要は次のとおりです。
どのオブジェクトがロックを同期しているかを知ることは、より安全なマルチスレッド プログラムを設計するのに役立ちます。
共有リソースへの同期アクセスをより安全にするためのテクニックが他にもいくつかあります:
1.パブリック/保護されたインスタンス変数の代わりに、プライベート インスタンス変数とその get メソッドを定義します。変数が public として定義されている場合、オブジェクトは同期メソッドの制御をバイパスして、外部から変数を直接取得して変更できます。これも JavaBean の標準的な実装方法の 1 つです。 ###2。インスタンス変数が配列や ArrayList などのオブジェクトである場合、上記のメソッドは依然として安全ではありません。外部オブジェクトが get メソッドを通じてインスタンス オブジェクトの参照を取得し、それが別のオブジェクトを指すと、プライベート変数が変わったら危ないんじゃないでしょうか?現時点では、get メソッドに同期を追加し、このプライベート オブジェクトの clone() のみを返す必要があります。これにより、呼び出し側はオブジェクトのコピーへの参照を取得します。
以上がsynchronized を使用して Java で同期メカニズムを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。