synchronizedキーワードは、Javaのマルチスレッドサポートの開始時から存在し、異なるスレッドからのコードブロックやメソッドへの排他的アクセスを保証します。これは、異なるスレッドから共有データに同時にアクセスする際に発生するレースコンディションとデータの不整合といった古典的な問題に対するJavaの回答です。
問題 マルチスレッド労働の際には、操作の「アトミック性」を確保し、オブジェクトの状態の矛盾した変更を防ぐ必要があります。synchronizedを誤って使用すると、デッドロック、パフォーマンスの低下、またはモニターオブジェクトの不正な選択による同期の欠如が引き起こされる可能性があります。
解決策 synchronizedキーワードを使用して、1つのスレッドだけが同時にその部分を実行することを保証する必要があります。シンクロナイザオブジェクトを慎重に選択し、長いクリティカルセクションを避け、より複雑なタスクにはjava.util.concurrentパッケージの特別なクラスを使用するべきです。
コードの例:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } } // 別のオブジェクトでコードの一部だけを同期: private final Object lock = new Object(); public void complexIncrement() { synchronized (lock) { // クリティカルセクション count++; } }
主な特徴:
synchronizedメソッドとsynchronizedブロックの違いは何ですか?
synchronizedメソッドはオブジェクト(またはstaticメソッドの場合はクラス)の「モニター」をブロックしますが、synchronizedブロックは明示的にモニターオブジェクトを指定できるため、より柔軟性があります。
一つのオブジェクトで異なるメソッドをsynchronizedした場合、どうなりますか?
両方のメソッドがsynchronizedでマークされている場合(staticでない限り)、両方とも自身のオブジェクト(this)をモニターとして使用します。一方のスレッドがどちらかのメソッドに入ることができない限り、他方のメソッドには入れません。
staticメソッドと通常のメソッドを同期できますか?それらはお互いにどうブロックされますか?
staticメソッドはクラスそのもの(Classオブジェクト)のモニターを使用し、通常のメソッドはインスタンスオブジェクトを使用します。したがって、static synchronizedメソッドと通常のsynchronizedメソッドはお互いをブロックしません。
開発者は異なるオブジェクトのメソッドを同期しますが、同じStringをモニターとして使用します。その結果、パフォーマンスが低下し、文字列がプールから再利用されることによる「偶発的な」デッドロックが発生します。
利点:
欠点:
クラス内部でのみ作成されたプライベートのfinalオブジェクトを使用して同期化し(private final Object lock)、クリティカルセクションは最小限の時間を要する。
利点:
欠点: