39

私はJavaに本当に慣れていないsynchronizedので、Javaでは「非常に高価」だと読みました。私が知りたいのは、何が高価で、どのように高価なのかということだけです。

ありがとう。

4

5 に答える 5

43

多分それはあなたが思うほど悪くはない

以前はひどいものでした(これが「非常に高価」だったと読んだ理由かもしれません)。これらのミームは死ぬのに長い時間がかかることがあります

同期にはどのくらいの費用がかかりますか?

キャッシュのフラッシュと無効化を含むルールのため、Java言語の同期ブロックは、通常、アトミックな「テストアンドセットビット」マシン命令で実装される多くのプラットフォームが提供するクリティカルセクション機能よりも一般的に高価です。プログラムに単一のプロセッサで実行されている単一のスレッドのみが含まれている場合でも、同期されたメソッド呼び出しは、同期されていないメソッド呼び出しよりも低速です。同期で実際にロックの競合が必要な場合は、複数のスレッドスイッチとシステムコールが必要になるため、パフォーマンスの低下が大幅に大きくなります。

幸い、JVMの継続的な改善により、Javaプログラム全体のパフォーマンスが向上し、各リリースとの同期の相対コストが削減されました。将来の改善が期待されています。さらに、同期のパフォーマンスコストはしばしば誇張されています。ある有名な情報源は、同期されたメソッド呼び出しは、同期されていないメソッド呼び出しよりも50倍も遅いと述べています。この声明は真実かもしれませんが、それはまた非常に誤解を招き、多くの開発者が必要な場合でも同期を回避するようになりました。

そうは言っても、並行プログラミングはまだ遅いかもしれませんが、それは今のところ純粋にJavaのせいではありません。細かいロックと粗いロックの間にはトレードオフがあります。粗すぎるのは明らかに悪いことですが、ロックのコストはゼロではないため、細かすぎる可能性もあります。

競合している特定のリソースを検討することが重要です。メカニカルハードディスクは、スレッドが増えるとパフォーマンスが低下する可能性がある例です。

于 2009-11-04T00:48:45.437 に答える
14

スレッドを使用していて、多数のスレッドがコードの同期されたセクションを通過する必要がある場合、一度に実行できるスレッドは 1 つだけであるため、コストがかかります。

ボトルネックのようなものです。

実行が許可されているかどうかをとにかくチェックする必要があるため、単一のスレッドを使用するとさらにコストがかかります。

同期セグメントの使用を減らすと、スレッドが実行できるかどうかを確認するためにスレッドを停止する必要がなくなります (もちろん、データを共有する必要はありません)。

同期の仕組みの概要については、こちらを参照してください。

http://img20.imageshack.us/img20/2066/monitor28synchronizatioc.png

Java スタイルのモニター

于 2009-11-04T00:49:28.923 に答える
9

これは Java に限ったことではありません。同期は、正しく行われないと、マルチスレッド環境で「コストがかかる」と見なされる可能性があります。Javaで特に悪いのかどうかはわかりません。

スレッドが同じリソースを使用する場合、スレッドが同時に実行されるのを防ぎます。しかし、それら同じリソースを使用するため、これ以上のオプションはありません (実行する必要があります)。

問題は、あまりにも大きな範囲でリソースを保護することがよくあることです。たとえば、不適切に設計されたプログラムは、配列内の個々の要素 (または配列のセクション) ではなく、オブジェクトの配列全体を同期する場合があります。

これは、要素 7 を読み取ろうとするスレッドが、要素 22 の読み取りまたは書き込みを行うスレッドを待たなければならないことを意味します。必要ありません。同期の粒度が配列レベルではなく要素レベルである場合、これら 2 つのスレッドは互いに干渉しません。

2 つのスレッドが同じ要素にアクセスしようとした場合にのみ、リソースの競合が発生します。そのため、一般的なルールとして、できるだけ小さなリソースのみを保護する必要があります (もちろん、同期の数には制限があります)。

しかし、正直なところ、1 つのリソースをめぐって 2 つのスレッドが競合することによるデータの破損が代替手段である場合、それがどれほど高くつくかは問題ではありません。アプリケーションを正しく作成し、パフォーマンスの問題が発生した場合にのみ心配します (「最初機能させてから、すばやく機能させる」というのが私のお気に入りのマントラです)。

于 2009-11-04T00:54:46.947 に答える
5

IBM のこの記事では、同期の背後にある要点が非常にうまくまとめられています。

キャッシュのフラッシュと無効化に関するルールのため、Java 言語の同期ブロックは、多くのプラットフォームで提供されるクリティカル セクション機能よりも一般にコストがかかります。クリティカル セクション機能は、通常、アトミックな「テストとビットの設定」マシン命令で実装されます。プログラムに 1 つのプロセッサで実行される 1 つのスレッドしか含まれていない場合でも、同期されたメソッド呼び出しは、非同期のメソッド呼び出しよりも低速です。同期に実際にロックの競合が必要な場合、いくつかのスレッド切り替えとシステム コールが必要になるため、パフォーマンスの低下は大幅に大きくなります。

于 2009-11-04T00:50:36.060 に答える
3

他の回答は、私が複製しようとしない技術的な詳細の適切なレベルを提供します。

私がすることは、記事の日付を確認することをお勧めします(著者の暗黙の能力と認識も同様です)。Javaでの同期は、以前の JVM では非常に低速でした。ただし、最近では大幅に改善されており、競合のない同期は想像以上に高速であり、競合のない同期も改善されています。

この質問はおそらく問題ではないことに注意してください。正確性を確保するために同期する必要がある場合は、正確性を確保するために同期する必要があります。速度が問題になるのは、(非常に効率的だが複雑なjava.util.concurrent.locks.AbstractQueuedSynchronizerを使用して) 代わりにロックレス実装を作成することを検討している場合、または代わりにタスクに別の言語を使用することを検討している場合のみです。

一般的に、同期は通常、最初の反復で使用するのに十分な速さであるというのが最良の結論だと思います。すべてのパフォーマンスの問題と同様に、最初は明確さと正確さのためにコーディングし、次に、アプリケーションの高価な部分であると測定したものだけを最適化します。通常、これは同期のコストではありません*。

于 2009-11-04T10:56:03.793 に答える