同期されたメソッドが別の同期されたメソッドを呼び出す場合、それはスレッドセーフですか?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
同期されたメソッドが別の同期されたメソッドを呼び出す場合、それはスレッドセーフですか?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
回答:
はい、メソッドをとしてマークするとsynchronized
、実際にこれを実行します。
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
スレッド呼び出しがmethod1からmethod2に入ると、ロックが保持されていることを確認しますthis
。これはすでに保持されており、通過できます。
スレッドがmethod1またはmethod2に直接入ると、ロック(this
)を取得できるまでブロックされ、その後入ります。
コメントでJamesBlackが指摘しているように、メソッド本体の内部で何をするかを知っておく必要があります。
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
が同期さConcurrentModificationException
れていないため、将来的にaを見ているため、突然スレッドセーフではなくmethod3
なり、スレッドBがで動作してmethod1
いるときにスレッドAによって呼び出される可能性があります。
method3
は安全でないスレッド操作を示していますが、リエントラント同期については注意が必要です。
Javaチュートリアルサイトhttp://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.htmlから
同じオブジェクトで同期されたメソッドの2つの呼び出しがインターリーブすることはできません。1つのスレッドがオブジェクトの同期メソッドを実行している場合、同じオブジェクトブロックの同期メソッドを呼び出す他のすべてのスレッドは、最初のスレッドがオブジェクトで完了するまで実行を一時停止します。
同期メソッドが終了すると、同じオブジェクトの同期メソッドの後続の呼び出しとの発生前の関係が自動的に確立されます。これにより、オブジェクトの状態への変更がすべてのスレッドに表示されることが保証されます
したがって、Javaは、2つのスレッドが同じメソッドを実行している場合、メソッドが同時に実行されるのではなく、次々に実行されることを保証します。
ただし、活性の問題に注意する必要があります。http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
そしてまた、あなたがuncessarilyロックされているかどうか、コード内の原因は、あなたが使用され、これをあなたのオブジェクトが唯一のあなただけのその変数をロックする必要がある一つの変数への同期アクセスを必要とする場合、オブジェクト全体をロックします、。
synchronized (this.someVar)
、参照がで保持されているオブジェクトを探していると言いますsomeVar
。区別は非常に重要です。