Java では、複数のスレッドが共有リソースにアクセスする場合、同時プログラミングにおいて同期が非常に重要です。これにより、一度に 1 つのスレッドだけがクリティカル セクションにアクセスするようになり、データの不整合が防止されます。同期はコードのメソッドまたはブロックに適用できます。メソッドとブロックの同期
Javaの逆文字列
同期の種類
- メソッドの同期: メソッド全体をロックして、一度に 1 つのスレッドだけがメソッドを実行できるようにします。
- ブロック同期: メソッド内のコードの重要なセクションのみをロックします。
複数のスレッドによってアクセスされる可変オブジェクトには同期が必要です。不変オブジェクトまたは読み取り専用アクセスには同期は必要ありません。
メソッドの同期
メソッドを同期するには、synchronized キーワードを追加します。これにより、一度に 1 つのスレッドだけがメソッドを実行できるようになります。
例 1: 非同期メソッド
Javaclass Line { public void getLine() { for (int i = 0; i < 3; i++) { System.out.println(i); try { Thread.sleep(100); } catch (Exception e) { System.out.println(e); } } } } class Train extends Thread { Line line; Train(Line line) { this.line = line; } public void run() { line.getLine(); } } public class Geeks { public static void main(String[] args) { Line obj = new Line(); Train t1 = new Train(obj); Train t2 = new Train(obj); t1.start(); t2.start(); } }
出力
0 0 1 1 2 2
説明: スレッド t1 と t2 がメソッドに同時にアクセスすると、出力が混合されます。
文字列Javaのインデックス
例 2: 同期メソッド
Javaclass Line { synchronized public void getLine() { for (int i = 0; i < 3; i++) { System.out.println(i); try { Thread.sleep(100); } catch (Exception e) { System.out.println(e); } } } } class Train extends Thread { Line line; Train(Line line) { this.line = line; } public void run() { line.getLine(); } } public class Geeks { public static void main(String[] args) { Line obj = new Line(); Train t1 = new Train(obj); Train t2 = new Train(obj); t1.start(); t2.start(); } }
出力
0 1 2 0 1 2
説明: データの一貫性を確保するために、一度に 1 つのスレッドだけがメソッドを実行します。
ブロック同期
ブロック同期は、メソッドの一部にのみ重要なコードが含まれる場合に使用されます。これにより、スレッドが重要でないコードを同時に実行できるようになり、パフォーマンスが向上します。
例: 同期ブロック
Javaimport java.util.*; class Geek { String name = ''; public int count = 0; public void geekName(String geek List<String> list) { synchronized(this) { name = geek; count++; } list.add(geek); } } public class GFG { public static void main(String[] args) { Geek gk = new Geek(); List<String> list = new ArrayList<>(); gk.geekName('Mohit' list); System.out.println(gk.name); } }
出力
Mohit
説明: ブロック更新名と回数のみが同期されます。リストへの名前の追加は同時に実行されます。
メソッドとブロックの同期
| 特徴 | メソッドの同期 | ブロック同期 |
|---|---|---|
| 範囲 | メソッド全体をロックします | コードの特定のブロックのみをロックします |
| パフォーマンス | 重要ではないコードに対して不必要なブロックが発生する可能性がある | 重要なセクションのみが同期されるため、より効率的です |
| ロック | メソッドのオブジェクトのロックを取得します | ブロックで指定されたオブジェクトまたはクラスのロックを取得します。 |
| 柔軟性 | 柔軟性が低いメソッド全体がロックされている | より柔軟な選択的な同期が可能 |
注意事項
- 同期されたメソッド/ブロックに入るスレッドはロックを取得し、終了時にロックを解放します。
- インスタンス メソッド/ブロック: オブジェクト レベルのロックを取得します。
- 静的メソッド/ブロック: クラスレベルのロックを取得します。
- Null オブジェクトの同期では NullPointerException がスローされます。
- wait()、notify()、およびnotifyAll()は、同期における重要なメソッドです。
- スレッドが異なるオブジェクトをロックしないように、非最終フィールドの同期は避けてください。
- synchronized キーワードは変数には適用できません。
利点
- マルチスレッド プログラムにおける共有リソースの相互排他を保証します。
- 同期されたインスタンスと静的メソッドは両方とも、異なるオブジェクトをロックするため、同時に実行できます。
制限事項
- 同時読み取りを防止して同時実行を制限します。
- 同期メソッドはパフォーマンスを低下させる可能性があります。クリティカルセクションのみのブロック同期を優先します。