ホームページ >Java >&#&チュートリアル >Javaでスレッド同期を実装する方法
方法 1: synchronized キーワードを使用する
Java の各オブジェクトには組み込みのロックがあるため、このキーワードを使用してMethod では、組み込みのロックがメソッド全体を保護します。このメソッドを呼び出す前に、組み込みロックを取得する必要があります。取得しないとブロックされます。
注: synchronized キーワードは静的メソッドを変更することもできます。この時点で静的メソッドが呼び出されると、クラス全体がロックされます。
注: 同期は高コストの操作であるため、同期の内容は最小限にする必要があります。通常、メソッド全体を同期する必要はなく、同期されたコード ブロックを使用してキー コードを同期するだけです。
synchronized キーワードは、共有データを保護するために使用されます。 「共有データ」に注意してください。どのデータが共有データであるかを区別する必要があります。
関連ビデオ チュートリアルの推奨事項:java ビデオ
例:
package com.gcc.interview.synchro; public class MybanRunnable implements Runnable{ private Bank bank; public MybanRunnable(Bank bank) { this.bank = bank; } @Override public void run() { for(int i=0;i<10;i++) { bank.save1(100); System.out.println("账户余额是---"+bank.getAccount()); } } }
package com.gcc.interview.synchro; class Bank{ private int account = 100; public int getAccount() { return account; } //同步方法 public synchronized void save(int money) { account+=money; } public void save1(int money) { //同步代码块 synchronized(this) { account+=money; } } public void userThread() { Bank bank = new Bank(); MybanRunnable my1 = new MybanRunnable(bank); System.out.println("线程1"); Thread th1 = new Thread(my1); th1.start(); System.out.println("线程2"); Thread th2 = new Thread(my1); th2.start(); } }
方法 2: 待機して通知
wait(): スレッドを待機状態にし、スレッドが保持しているオブジェクトのロックを解放します。
sleep(): 実行中のスレッドをスリープ状態にします。これは静的メソッドです。InterruptedException をキャッチするには、このメソッドを呼び出します。
notify(): 待機状態のスレッドをウェイクアップします。このメソッドを呼び出すとき、待機状態のスレッドを正確にウェイクアップすることはできないことに注意してください。代わりに、JVM がどのスレッドをウェイクアップするかを決定し、優先順位ではありません。
Allnotity(): 待機状態にあるすべてのスレッドをウェイクアップします。ウェイクアップしたすべてのスレッドにオブジェクト ロックを与えるのではなく、スレッドを競合させることに注意してください。
方法 3: 特殊なドメイン変数 volatile を使用してスレッド同期を実現する
a.volatile キーワードは、ドメイン変数にアクセスするためのロックフリーのメカニズムを提供します
# b. volatile を使用してフィールドを変更することは、フィールドが他のスレッドによって更新される可能性があることを仮想マシンに伝えることと同じです c. したがって、フィールドが使用されるたびに、値を使用する代わりにフィールドを再計算する必要があります。レジスタ内d.volatile はアトミック操作を提供せず、最終型変数の変更にも使用できません。 例: 上記の例では、アカウントの前に追加 揮発性の変更により、スレッドの同期を実現できます。
//只给出要修改的代码,其余代码与上同 class Bank { //需要同步的变量加上volatile private volatile int account = 100; public int getAccount() { return account; } //这里不再需要synchronized public void save(int money) { account += money; } }注意: マルチスレッドにおける非同期問題は、主にドメインへの読み書き時に発生しますが、ドメイン自体がこの問題を回避できる場合は、ドメインの運用方法を変更する必要はありません。最終フィールド、ロックで保護されたフィールド、および揮発性フィールドを使用すると、非同期の問題を回避できます。
方法 4: 再入ロックを使用してスレッド同期を実現する
同期をサポートするために、新しい java.util.concurrent パッケージが JavaSE5.0 に追加されました。 ReentrantLock クラスは、Lock インターフェイスを実装する再入可能で相互排他的なロックであり、同期されたメソッドおよびブロックを使用する場合と同じ基本的な動作とセマンティクスを持ち、その機能を拡張します。 ReenreantLock クラスの一般的に使用されるメソッドは次のとおりです。 注: ReentrantLock() には公平なロックを作成できる構築メソッドもありますが、プログラムの実行効率が大幅に低下する可能性があるため、推奨されませんprivate int account = 100; private ReentrantLock lock = new ReentrantLock(); public int getAccount() { return account; } //同步方法 public void save(int money) { lock.lock(); try { account+=money; } finally { lock.unlock(); } }注: ロック オブジェクトと同期キーワードの選択について: a. どちらも使用せず、java.util を使用することをお勧めします。 .concurrent パッケージ 提供されるメカニズムは、ユーザーがロック関連のすべてのコードを処理するのに役立ちます。 b. synchronized キーワードがユーザーのニーズを満たすことができる場合は、コードを簡素化できる synchronized を使用します c. より高度な機能が必要な場合は、ReentrantLock クラスを使用します。 , 時間内にロックを解放することに注意してください。そうでないとデッドロックが発生します。通常、ロックはfinally コードで解放されます。#方法 5: ローカル変数を使用してスレッド同期を実現します
ThreadLocal を使用して変数を管理する場合、変数を使用する各スレッドは変数のコピーを取得し、コピーは互いに独立しているため、各スレッドは他のスレッドに影響を与えることなく、変数の独自のコピーを自由に変更できます。 。
ThreadLocal クラスの一般的に使用されるメソッド
//只改Bank类,其余代码与上同 public class Bank{ //使用ThreadLocal类管理共享变量account private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){ @Override protected Integer initialValue(){ return 100; } }; public void save(int money){ account.set(account.get()+money); } public int getAccount(){ return account.get(); } }注: ThreadLocal と同期メカニズム
a.ThreadLocal と同期メカニズムは両方とも複数の問題を解決する スレッド内の同じ変数のアクセス競合の問題。
b. 前者は「空間を時間に交換する」方法を採用し、後者は「時間を空間に交換する」方法を採用します。
おすすめの関連記事とチュートリアル:
ゼロから始める Java 入門以上がJavaでスレッド同期を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。