Jvm reading-synchronization

2,136 views

Published on

Jvm reading-synchronization

  1. 1. Locking and Synchronization第7回JVMソースコードリーディングの会 (OpenJDK) 中村 実 nminoru@nminoru.jp nminoru1975@gmail.com Twitter @nminoru_jp 1
  2. 2. Javaのスレッド排他機構• Objectはすべて同期オブジェクトになれる – Critical section型の排他処理 – 再帰的なロックも可能• 文法 – synchronizedメソッド – Synchronized文 • バイトコードレベルではmonitorenter、 monitorexit – wait & notify 2
  3. 3. Java Synchronizationの問題点• 安易に書けるため使いすぎる – 不要な場所にもsynchronizedを書いてしまう。 – 衝突しないsynchronizationが異常に多い。 class Hoge { int _hoge; public synchronized int getHoge() { return _hoge; } public synchronized void setHoge(int hoge) { _hoge = hoge; } } 3
  4. 4. Java Synchronizationの実装方法• 基本(Biased Locking以前) – -XX:-UseBiasedLocking• Biased Locking – -XX:+UseBiasedLocking(OpenJDK6ではデフォル ト) 4
  5. 5. Hotspotのlock関係のオプション-XX:+UseBiasedLocking BiasedLockingを有効に。-XX:-TraceMonitorInflation Inflation/deflation発生時にトレースを表示。-XX:-TraceBiasedLocking BaisedLockingに変更にトレースを表示。-XX:BiasedLockingStartupDelay=4000 VM起動後に時間をおいてからbiased locking を有効化する。その待機時間をミリ秒で指定。-XX:BiasedLockingBulkRebiasThreshold=20 Threshold of number of revocations per type to try to rebias all objects in the heap of that type-XX:BiasedLockingBulkRevokeThreshold=40 Threshold of number of revocations per type to permanently revoke biases of all objects in the heap of that type-XX:BiasedLockingDecayTime=25000 Decay time (in milliseconds) to re-enable bulk rebiasing of a type after previous bulk rebias-XX:-PrintBiasedLockingStatistics Print statistics of biased locking in JVM 5
  6. 6. 基本ロック 6
  7. 7. 基本ロックの方針• 衝突しないロック(uncontened lock)を効率 的に処理する• Phase1 (Lightweight) Locked – Unlock状態のオブジェクトに最初のスレッド がロックを行った状態。 – Thread-localなデータ構造だけで対応。• Phase2 Inflated – 第二以降のスレッドがロックを行い、thread- globalなデータ構造に変更する。これを inflationと呼ぶ。 7
  8. 8. ロックの構造体はどこにある?• oopの中にはない。• oopの第一ワードの_markは多目的用途で、 ロック時には切り替える(markOop.hpp) _mark hash code age 0 01 Normal(unlocked) _klass Pointer to basic lock 00 Locked Fields Pointer to monitor 10 Inflated lock JavaThread* epoch age 1 01 Biased 8
  9. 9. Phase 1• 最初のスレッドのロックはlocked状態へ遷移 – Interpreter frame上にBasicObjectLockを積むことでロックを表現 – 元の_markの内容を_displaced_headerへ退避 – _markはBasicLockの位置をComapre-And-Swap(CAS)で書き込む。 Object Interpreter frameTo basic lock 00 BasicLock _klass BasicObjectLock _lock : BasicLock _displaced_header Fields _obj 9
  10. 10. Phase 1• 処理コード InterpreterRuntime::monitorenter in interpreterRuntime.cpp:585 ObjectSynchronizer::fast_enter in synchronizer.cpp:155 ObjectSynchronizer::slow_enter in synchronizer.cpp:201 Under src/share/vm/runtime/• Recursive lockは? – Interpreter frameに複数のBasicObjectLockを積むことで 実現。• Unlockは – Stack unwind + α が unlock 処理。 – ObjectSynchronizer::fast_exit 10
  11. 11. Phase2 ObjectMonitor Object _header 前にあった_markを保存To monitor 10 _object ロック対象のoop _klass _owner ロックオーナー _recursions ロックの再帰回数(初回は0) Fields _cxq _EntryList … Owning Thread ObjectWaiter ObjectWaiter Blocked Thread _next _next _prev _prev Blocked Thread _thread _thread … … 11
  12. 12. Phase2• 処理コード – ObjectSynchronizer::inflate (inflation処理) – ObjectMonitor::enter (inflation後のロック処理)• 複数のスレッドが同時にinflationを試みるこ とがあるが、objectの_markをCASで書き換え ることで衝突判定している。• ObjectMonitorはスレッド毎にfree list管理され ておりinflateを実行しているスレッドが供出 する。 – ObjectSynchronizer::omAlloc 12
  13. 13. Biased Locking 13
  14. 14. Biased Lockingのコンセプト• もっとCAS命令の削除を – 基本ロックでは1回のロックで最低1回のCAS 命令を使う。• Biased Locking [Russell06] – あるスレッドからロックされたオブジェクト は、また同じスレッドからロックされる傾向 がある。 – オブジェクトの中にスレッド情報を埋め込ん で、特定のスレッドに偏っている(biased)こと を示す。そのスレッドからのロックはCASな しで済ませることが可能に。 14
  15. 15. Biased Lockingのコンセプト• どこにbiased threadを挿れるのか? – hash codeを潰す。 hash code age 0 01 Normal(unlocked) Thread id epoch age 1 01 Biased – hashcodeのフィールドは初期値は0で、hashが 最初に呼ばれた時に動的に設定される。 • hash()が呼ばれるとbiasedは解ける。 15
  16. 16. Biased Lockingのコンセプト• オブジェクト生成時はanonymously biased• 最初のスレッドがロックすると、そのスレッドのbiasがかかる(ここはCASが 必要)• Biasedのかかったスレッドがロックする場合は_markに変更が不要 – store-free- biased locking• ロックの衝突やその他が起きるとbiasをかけるのを止めて通常の状態に戻る。 – 以降、基本ロックを使用して元には戻らない。 Biasable Mode Normal Mode Initial lock 0 1 01 T 1 01 … 0 01anonymously biased biased toward given thread … 0 00 Revoke bias bulk rebias 16
  17. 17. Store-free biased locking(SFBL)BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS){ markOop mark = obj->mark(); if (mark->is_biased_anonymously() && !attempt_rebias) { // 初めてのロック } else if (mark->has_bias_pattern()) { Klass* k = Klass::cast(obj->klass()); markOop prototype_header = k->prototype_header(); if (!prototype_header->has_bias_pattern()) { // このクラスでは biased locking が許可されていない return BIAS_REVOKED; } else if (prototype_header->bias_epoch() != mark->bias_epoch()) { // epoch が一致しないので rebiased するか revoke する retrun } } HeuristicsResult heuristics = update_heuristics(obj(), attempt_rebias); if (heuristics == HR_NOT_BIASED) { return NOT_BIASED; // biased lokcing に成功 } 17
  18. 18. Bulk rebiasing and revocation• Bulk rebiasing – どのスレッドでbiasをかければいいのか時間 変化するので、一定周期でbiased toward given threadをanonymously biasedに戻す。• Bulk revocation – ある種のオブジェクトはbiased lockingに向か ない。 18
  19. 19. もっとCAS命令を減らしたい 19
  20. 20. Synchronized getterはCASを使わない• Software Optimistic Lock Elision for Read-Only ciritical sections(SOLERO) [Nakaie10] – Objectのヘッダにカウンタを用意 – JITを使って解析 Counter bits xx • オブジェクトのフィールドを変更するsync. method はcounerをアトミックに+1 • オブジェクトのフィールドを変更しない sync.methodはcounter読む→フィールド読む →counter再読み込みする。 • Counterが一致すれば成功。不一致なら通常の synchronization方式で再実行 20
  21. 21. Synchronized getterはCASを使わないclass Hoge { class Hoge { <<counter>> int _hoge; int _hoge; public synchronized int getHoge() { public synchronized int getHoge() { return _hoge; old = counter; } ret = _hoge; if (old == counter) return ret; // 再実行 } public synchronized void setHoge(int hoge) { public synchronized void setHoge(int hoge) { _hoge = hoge; fetchadd counter +1 } _hoge = hoge; }} } 21
  22. 22. 参考文献• David Dice, “Implementing fast Java monitors with relaxed locks”, In proceedings of the Java Virtual Machine, Research and Technology Symposium(JVM’01), April 2001, pp.79-90.• Kenneth Russell and David Detlefs, “Eliminating Synchronization-Related Atomic Operations with Biased Locking and Bulk Rebiasing”, OOPSLA’06, pp.• Takuya Nakaike and Maged M. Michael, “Lock Elision for Read-Only Critical Section in Java”, PLDI’10 22

×