ここでは、スレッドの動きを少し詳しくみていきます。
複数のスレッドから、同一インスタンス、同一クラスの異なるインスタンス、の各メソッドに同時アクセスした場合、同時実行可能・不可能なパターンについて、まとめてみました。
以下のサンプルコードを見てください。
■サンプルコード
class SyncTest(){
public void insA(){}
public void insB(){}
public synchronized void insSyncA(){}
public synchronized void insSyncB(){}
public static void clsA(){}
public static void clsB(){}
public static synchronized void clsSyncA(){}
public static synchronized void clsSyncB(){}
}
上記の様に、SyncTestクラスが宣言されているとします。
この場合、複数のスレッドからこのインスタンスのメソッドに同時アクセス可能か・否かをパターン表にて示します。
※複数のスレッドで同時に実行できるパターンには「○」、実行できないパターンには「×」を記述しています。「-」のパターンは他のパターンと重複しているため、考慮していません。
※X、Yは、SyncTestクラスの異なるインスタンスを表すとします。
1. 2つのスレッドが、同じインスタンスXの各メソッドに同時アクセスした場合
| X | ||||||||||
| SyncTest | ||||||||||
| .insA() | .insB() | .insSyncA() | .insSyncB() | .clsA() | .clsB() | .cclSyncA() | .clsSyncB() | |||
| X | .insA() | ○※1 | ○※1 | ○※1 | - | ○※1 | - | ○※1 | - | |
| .insSyncA | - | - | ×※2 | ×※2 | ○※3 | - | ○※3 | - | ||
| SyncTest | .clsA() | - | - | - | - | ○※4 | ○※4 | ○※4 | - | |
| .clsSyncA | - | - | - | - | - | - | ×※5 | ×※5 | ||
2. 2つのスレッドが、異なるインスタンスX、Yの各メソッドに同時アクセスした場合
| Y | ||||||||||
| SyncTest | ||||||||||
| .insA() | .insB() | .insSyncA() | .insSyncB() | .clsA() | .clsB() | .cclSyncA() | .clsSyncB() | |||
| Y | .insA() | ○※1 | ○※1 | ○※1 | - | ○※1 | - | ○※1 | - | |
| .insSyncA | - | - | ○※6 | ○※6 | ○※3 | - | ○※3 | - | ||
| SyncTest | .clsA() | - | - | - | - | ○※4 | ○※4 | ○※4 | - | |
| .clsSyncA | - | - | - | - | - | - | ×※6 | ×※6 | ||
■各パターンの説明
| 注釈No. | 説明 |
| ※1 | synchronizedではないインスタンスメソッドは、複数のスレッドから実行可能(例え、他でsynchronizedメソッドを実行しているスレッドがあっても実行可能) |
| ※2 | 同じインスタンスのsynchronizedインスタンスメソッドは、複数のスレッドから同時実行不可能(ロックの対象となるインスタンスが同一なため) |
| ※3 | インスタンスメソッドとクラスメソッドとでは、複数のスレッドから同時実行可能(そもそも、インスタンスメソッド・クラスメソッドがsynchronizedであったとしても、ロックの対象がインスタンスとクラスオブジェクトで異なるため) |
| ※4 | synchronizedではないクラスメソッドは、複数のスレッドから同時実行可能(例え、他でsynchronizedメソッドを実行しているスレッドがあっても実行可能) |
| ※5 | synchronizedクラスメソッドは、複数のスレッドから同時実行不可能(ロックの対象となるクラスオブジェクトが同じなので) |
| ※6 | 異なるインスタンスの場合、synchronizedインスタンスメソッドは、複数のスレッドから同時実行可能(ロックの対象となるインスタンスが異なるので) |