ホームページ  >  記事  >  Java  >  Java が Synchronized を使用してマルチスレッド同期を実現する方法

Java が Synchronized を使用してマルチスレッド同期を実現する方法

PHPz
PHPz転載
2023-04-30 16:19:07994ブラウズ

同期を使用する理由

1. システム内のクラスにアクセスするにはマルチスレッドを使用する必要があります;

2. クラス内にはクラス変数、またはクラス内にはメソッドがあります。パブリック リソースへのアクセス (外部ファイルの読み取りおよび書き込みなど)。

同期ロックによってロックされる内容は何ですか?

Synchronized をメソッドまたは変数の前に追加すると、クラス オブジェクトがロックされます。各オブジェクトにはロックが 1 つだけ関連付けられています。

次の例は、さまざまな状況における同期効果をリストしたものです

1. Synchronized がメソッド (同期メソッド、ロック クラス インスタンス) に追加されます

Java コード

public class Demo1 {             public synchronized void m1(){             //...............         }             public void m2(){             //............                 synchronized(this){                 //.........             }                 //........         }     }

これら 2 つの書き込みメソッドの効果は同じで、すべてのクラス インスタンス オブジェクトをロックします。クラス インスタンス オブジェクト:demo = new Demo1() があり、2 つのスレッド:thread1、thread2 があり、どちらもデモ オブジェクトを呼び出している場合、同時に thread1 が demo.m1() を呼び出すと、thread2 は次のようになります。時間内に、demo.m1() と demo.m2() にアクセスできません。thread1 がデモ オブジェクトのロックを使用しているため、他のスレッドに配布して使用することはできません。

ただし、thread1 が呼び出した場合demo1.m1() 、 thread2 は異なる Demo1 クラス オブジェクト インスタンスを呼び出すため、demo2.m1() を同時に呼び出すことができます。

2. 変数に Synchronized を追加します (synchronized ブロック、ロック クラス インスタンス)

Java コード

public class Demo2 {         Object a = new Object();         Object b = new Object();             public void m1(){             //............                 synchronized(a){                 //.........             }                 //........         }             public void m2(){             //............                 synchronized(b){                 //.........             }                 //........         }     }

この場合は、コード ブロック ロックが実装されており、ロックされたオブジェクトは変数 a または b です (a と b は非静的であることに注意してください) クラス インスタンス オブジェクトがある場合: demo = new Demo2()、および他の 2 つのスレッドがある場合: thread1、thread2 、両方ともデモ オブジェクトと呼ばれ、同時に、スレッド 1 が demo.m1() を呼び出すと、スレッド 2 はその間、demo.m2() にアクセスできますが、demo.m1() の同期ブロックにはアクセスできません。スレッド 1 によってブロックされています。ロックされています。

3. 同期ロック クラス変数、つまり静的変数 (属性の場合もあればメソッドの場合もあります) (クラス オブジェクトのロック)

Java コード

public class Demo3 {         static Object o = new Object();             public static synchronized void m1() {             //....         }             public static void m2() {             //...             synchronized (Demo3.class) {                 //.....             }             //.....         }             public static void m3() {             //..........             try {                 synchronized (Class.forName("Demo3")) {                   //............                 }             } catch (ClassNotFoundException ex) {             }             //.............         }             public static void m4() {             //............            synchronized(o){              //........            }             //..........         }     }

上記の 4 つの方法で得られる効果は同じです。ロックされたオブジェクトはすべてクラス Demo3 であり、クラス インスタンス オブジェクトではありません。つまり、マルチスレッドでは、共有リソースはクラス オブジェクトではなくクラスに属します。この場合、スレッド 1 がこれら 4 つのメソッドのいずれかにアクセスすると、他のスレッドはこれら 4 つのメソッドに同時にアクセスできなくなります。

4. クラスメソッドは複数のスレッドに共通のリソースにアクセスしますが、そのリソースは可変です、この場合も同期が必要です

Javaコード

public class Demo4 {         static String path = "file path";             public void readConfiFile() {             synchronized (path) {                // 读取该path指定的文件。             }             }             public void writeConfiFile() {             synchronized (path) {                 //写信息到该path指定的文件。             }         }     }

この場合、クラス インスタンス オブジェクトではなくクラス変数としてロックする必要があります。これは、クラス インスタンス オブジェクトのリソース共有ではなく、変数イメージの一種のクラス リソース共有であるためです。

スレッドには成功と失敗があり、うまく使えばパフォーマンスを向上させることができますが、うまく使わないとシステムに際限のないトラブルを引き起こすことになります。

PS: スレッド同期には多くのシステム オーバーヘッドが必要なため、スレッド同期を使用する場合は、必要がない場合は同期機能を使用しないようにしてください。

以上がJava が Synchronized を使用してマルチスレッド同期を実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。