同期ブロックでのみ呼び出されるメソッド foo()があるとします。
メソッドを作っている
synchronized void foo() {..}
ちょうど対
void foo() {..}
冗長または悪い習慣ですか、それともメソッドの意図をより明確にしますか? メソッド署名に synchronized キーワードがあると、プログラムが遅くなりますか? より良いプラクティスは何か、または全体像の一部が欠けているかどうか疑問に思っています。
ありがとう。
同期ブロックでのみ呼び出されるメソッド foo()があるとします。
メソッドを作っている
synchronized void foo() {..}
ちょうど対
void foo() {..}
冗長または悪い習慣ですか、それともメソッドの意図をより明確にしますか? メソッド署名に synchronized キーワードがあると、プログラムが遅くなりますか? より良いプラクティスは何か、または全体像の一部が欠けているかどうか疑問に思っています。
ありがとう。
冗長ではなく、実際には、既に保持しているロックを同期するのがかなり一般的です。
スレッドセーフなものとそうでないものの境界が明確に定義されている API は、操作が容易であり、最適な境界はおそらくクラス レベルにあります。したがって、クラスの残りの部分がスレッドセーフであり、foo() メソッドが同期されていればスレッドセーフである場合は、それを行って、クラスのドキュメントにメモしておくこともできます。foo() を同期すると、スレッドセーフな呼び出しとスレッドセーフでない呼び出しが混在する API が得られる場合、後で混乱を招くことになります。
パフォーマンスに関しては、それが問題になるとは思えません (競合していないロックのオーバーヘッドは最小限に抑える必要があります)。コードを動作させてから、高速化する必要があるかどうかを確認してください。
通常、これはfoo()
がアトミック アクション自体ではないことを意味します。おそらく不変条件は保持されず、より大きな同期スキームの一部にすぎません。
そうしないと、読者が間違っsynchronized
た考えを得る可能性があります。そしてそれも少し遅いです。
代わりに、次のことができます。
void foo()
{
assert Thread.holdsLock(this);
...
}
それは2つの目的を果たします
synchonized(this)
このメソッドは外側のブロック内でのみ呼び出すことができることを文書化するメソッドfoo()
がクラス A にあり、呼び出し元コード (同期ブロック内で呼び出す) が別のクラス B にあるとします。
私のアドバイスは、 A のメソッドを作成しないことsynchronized
です。シングルスレッド プログラムでは、呼び出しが体系的に遅くなるためです。
ご指摘のとおり、同期ブロックを使用して、クライアントクラス(Bなど)に同期ジョブを実行させる方がよいでしょう。
要約すると、同期されたメソッドを宣言しないことをお勧めします。これは柔軟性が高いためです。クラスを使用して外部同期ブロックを使用してスレッドセーフなプログラムを作成し、高速なシングルスレッド アプリケーションを作成することもできます。クラス A がスレッドセーフでないことをユーザーに警告することもできます。