2012年5月1日火曜日

BEA JRockit でのシン ロック、ファット ロック、再帰的ロック、および競合するロックについて


BEA JRockit でのシン ロック、ファット ロック、再帰的ロック、および競合するロックについて

ここでは BEA JRockit での種々のロックについて説明します。

まず最も簡単な部分から説明しましょう。それは再帰的ロックです。再帰的ロックは次のような場合に発生します。

synchronized(foo) {  // スレッドが初めてロックを取得する
  synchronized(foo) {  // ここでロックが再帰的に取得される

再帰的ロックの取得は何レベルか下のメソッド呼び出しでも発生することがありますが、これは問題ありません。再帰的ロックの取得は必ずしもまずいプログラミングとは言えません。少なくとも別のメソッドで行われる場合は問題になりません。

幸い、JRockit での再帰的ロックの取得は非常に高速です。実際、ロックを再帰的に取得するコストは、ほとんど無視できるくらい小さなものです。このことは、そのロックがもともとシン ロックとして取得されていてもファット ロックとして取得されていても変わりません (これらのロックについては、後ほど詳しく説明します)。


標高の高い薬の高血圧

ここで競合について少し触れておきましょう。競合が起きるのは、スレッドがロックを取得しようとしたとき、そのロックが取得できない状態にある (つまり、別のスレッドが保持している) 場合です。競合はパフォーマンスの点で常にコストがかかります。そのコストがどれくらいになるかは、いろいろな要因によって違ってきます。コストについては後でもう少し詳しく説明します。

パフォーマンスを重視するなら、できる限り競合を避ける努力をすべきでしょう。しかし、あいにく競合を避けることのできない状況が多いのです。複数のスレッドが同じ共有リソースに同時にアクセスしなければならないアプリケーションでは、競合は避けられません。しかし、設計をうまくすれば痛みを軽減することはできます。同期ブロックを使いすぎないように注意してください。激しく競合するロックを保持しているときに実行する必要のあるコードを最小限に抑えてください。競合しやすいとわかっているロックならば、1 つのロックで無関係なリソースを保護するのは避けてください。

原理上、アプリケーション開発者としてできるのはそれだけです。可能ならば競合を避けるようにプログラムを設計してください。JRockit のロック動作を一部変更するための実験的なフラグがいくつかありますが、これらを使用するのはやめた方がよいでしょう。デフォルト値は慎重に選ばれたものなので、これを変更しても、むしろパフォーマンスが悪化する可能性の方が高いからです。

とはいえ、アプリケーション開発者として JRockit が自分のアプリケーションに何をしているのか知りたいと思うのは当然です。そこで、JRockit におけるロック方式について、もう少し詳しく説明することにします。

Java のオブジェクトはすべて潜在的なロック (モニタ) です。この潜在性は、スレッドがそのオブジェクトの同期ブロックに入るとすぐに実際のロックとして顕在化します。このようにしてロックが「誕生」すると、それは「シン ロック」というロックになります。シン ロックには以下の特性があります。


不安障害や不安障害と
  • ロックに関するすべての情報がオブジェクト自身に格納されるため、余分なメモリを必要としない。
  • 取得が素早く行われる。
  • そのロックを取得しようとする他のスレッドが自分自身を競合として登録できない。

シン ロックの取得で最も高くつく部分は CAS (compare-and-swap) 操作です。これはアトミックな命令です。つまり、CPU 命令に関する限り、遅いということです。それでも、ロックの他の部分 (競合全般およびファット ロックの取得) に比べると非常に高速です。

おおむね競合しないロックについては、シンロックは非常に優れています。ロックがない場合に比べてわずかなオーバーヘッドがあるだけです。多くの (とりわけクラス ライブラリの) Java コードが同期化を多用するので、これは好ましいことです。

しかし、ロックが競合することになれば、たちまち何が最も効率的か単純に断じることはできなくなります。ロックの保持される時間が非常に短くて、JRockit がマルチ CPU (SMP) マシン上で動作しているなら、最善策は「スピンロック」です。スピンロックとは、ロックを必要としているスレッドがタイトなループの中で「スピン」しながら、そのロックがまだ取得されているかどうか継続的にチェックすることです。ということは、当然、ある程度のパフォーマンス ロスがあります。実際のユーザ コードが実行されるわけではなく、他のスレッドに振り向けることもできる時間を CPU が「浪費」しているからです。とはいえ、わずか数サイクルのうちに他のスレッドがそのロックを解放するなら、この方法をとる方が有利だと言えるでしょう。これが「競合するシン ロック」です。

ロックがすぐに解放されないのであれば、競合に対してこの方法を使用しているとパフォーマンスが悪くなります。その場合、ロックは「ファット ロック」に「引き上げ」られます。ファット ロックには以下の特性があります。


私の足と腰の痛みである
  • ロックを取得したがっているスレッドのリストの分だけ余分なメモリを若干必要とする。
  • 取得に比較的時間がかかる。
  • 1 つまたは複数のスレッドがそのロックに対するキューイング (ブロッキング) として登録できる。

ファット ロックの競合に遭遇したスレッドは、自分自身をそのロックに対するブロッキングとして登録し、スリープ状態になります。つまり、OS によって割り当てられた時間の残りの分を放棄するということです。これは CPU が実際のユーザ コードの実行に使われることを意味しますが、それでもスピンロックに比べると余分なコンテキスト切り替えで高くつきます。スレッドがこれを行うと、「競合するファット ロック」が生じます。

競合している最後のスレッドがファット ロックを解放しても、そのロックは通常はファットのままです。たとえ競合がなくても、ファット ロックの取得はシン ロックの取得よりも高くつきます (ただし、ファット ロックまたはシン ロックをもう一方に変換するよりは安上がりです)。そのロックをシンにした方が有利だと JRockit が思えば (基本的に、競合が単なる「不運」であって、ロックが通常は競合しないなら)、そのロックを再びシン ロックに「引き下げる」かもしれません。

ロックについての特記事項 : ロックに関して wait/notify/notifyAll が呼び出された場合、それは自動的にファット ロックに引き上げられます。そのため (それだけが理由ではありませんが)、1 つのオブジェクトに対して、通知のためのロックを他の何らかのロック方式とともに使用することは避けてください。

JRockit は複雑な一群のヒューリスティックを使って以下のような事柄も決定します。


  • シン ロックに関していつ (そしてどれだけの時間) スピンロックし、競合でそれをいつファット ロックに引き上げるか。
  • ファット ロックをシン ロックに戻すかどうか、またいつ戻すか。
  • パフォーマンスを上げるために、競合するファット ロックに関して公平さを放棄するかどうか、またいつ放棄するか。

これらのヒューリスティックは動的に適応できます。つまり、実行されている現実のアプリケーションに合うように自動的に変化するということです。

シン ロックとファット ロックの間での切り替えは JRockit によって自動的に行われ、アプリケーションのパフォーマンスが最大になるロックの種類が選ばれるので、シン ロックとファット ロックの間のパフォーマンス上の違いは、実はユーザが心配することではありません。この問題について一般的な解を示すのは不可能です。なぜなら、システムによって CPU の数、CPU の種類、システムの他の部分 (メモリやキャッシュ) などの要因に違いがあるからです。さらに、個々のシステムに関しても、よい解を示すことが非常に難しいのです。競合するシン ロックでのスピンで費やされる時間を正確に判定するのは特に注意を要することです。なぜなら、JRockit は諦める前にわずか数個のマシン命令を数回ループするだけなので、これをプロファイリングすると、この時間に大きな影響を与え、実際とは違ったパフォーマンス イメージを生み出すことになるからです。

まとめ : パフォーマンスを重視している場合は、ロックで競合が起きないようにアプリケーションを変更できるなら、ぜひそうしてください。競合を避けることができないなら、競合が起きるコードを最小限に抑えるよう努力してください。そうすれば、JRockit はアプリケーションを可能な限り高速に実行すべく全力を挙げるでしょう。JRA によってもたらされるロック情報をヒントとして利用してください。ファット ロックは激しくあるいは長い時間競合している可能性があります。コーディングを工夫して、ファット ロックで競合が最小限になるよう努めてください。



These are our most popular posts:

再帰 - その他 - IT用語 - ビジネスEX

再帰とは、あるものの定義や記述に、それ自身が含まれること。そのような定義を「再帰 的定義」という。 プログラミングの分野で、関数やメソッドなどの記述の中に、その関数 など自体への呼び出しを行なうコードが含まれることを「再帰呼び出し」(recursive call: ... read more

再帰CB400SB ラムちゃんと共に バイク

2011年1月15日 ... バイク - やっと再帰したバイクLIFE。日常生活と愛車CB400SBと写真を!ほんわか まったり ... 身体は右腕の痛みが取れず、アクセルを捻っても痛いのでまだまだ時間は かかりそうです。 腰も同じくです。 人身解決はまだまだ先になりそうです ... read more

bind9.3系での再帰問い合わせ対策

bind9.3系での再帰問い合わせ対策 ... 再帰問い合わせを制限するのだからallow- recursionだけで~という考えですが、allow-queryオプションを設定しないとそれ以外の クエリは許可されてしまいます(デフォルト .... 頭痛持ちなので、痛み止めが手放せませ ん。 read more

回帰熱(再帰熱) とは - コトバンク

家庭医学館 回帰熱(再帰熱)の用語解説 - [どんな病気か] 回帰熱スピロヘータの感染 によっておこる伝染病で、病人や、このスピロヘータを保有するネズミ、リスなどから、 シラミ、ダニの媒介(ばいかい)で人間に感染します。 アジア・アフリカ・アメリカ大陸の 熱帯 ... read more

Related Posts



0 コメント:

コメントを投稿