4

OpenJDK6のhotspot/src/share/vm/prims/unsafe.cppコードスニペット(1082行目から)は次のとおりです。

// JSR166 ------------------------------------------------------------------

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
  UnsafeWrapper("Unsafe_CompareAndSwapObject");
  oop x = JNIHandles::resolve(x_h);
  oop e = JNIHandles::resolve(e_h);
  oop p = JNIHandles::resolve(obj);
  HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
  if (UseCompressedOops) {
    update_barrier_set_pre((narrowOop*)addr, e);
  } else {
    update_barrier_set_pre((oop*)addr, e);
  }
  oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
  jboolean success  = (res == e);
  if (success)
    update_barrier_set((void*)addr, x);
  return success;
UNSAFE_END

キーメソッドoopDesc::atomic_compare_exchange_oopも追加されています。

 inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
                                                    volatile HeapWord *dest,
                                                    oop compare_value) {
      if (UseCompressedOops) {
        // encode exchange and compare value from oop to T
        narrowOop val = encode_heap_oop(exchange_value);
        narrowOop cmp = encode_heap_oop(compare_value);

        narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp);
        // decode old from T to oop
        return decode_heap_oop(old);
      } else {
        return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);
      }
    }

JVMのコンテキストでのこのコードの目的は何ですか?私はC++の経験がありません。

Atomic :: cmpxchg&Atomic :: cmpxchg_ptrはOSとCPUに依存し、32ビット/64ビットに依存します。したがって、JVMはここで分割されます。

編集

steve-Oが指摘したように、CASにはABA問題としての弱点があるため、マルチスレッド環境でCASが正しいことを確認するには、ここでメモリバリアが必要です。また、CASにはアドレス、古い値、新しい値の3つのパラメーターが必要になるため、このプロセスには最新のCPUが必要です。

編集

新しいC++0x標準(現在正式に公開されていませんか?)では、JVMを分割する必要がないということですか?少なくとも、ソースコードレベルでは。バイナリは引き続き分割できますが、C++コンパイラによって処理されます。

4

2 に答える 2

5

これはCASAPIのJNIラッパーであり、IA64アーキテクチャのメモリバリアを備えています。

編集: CASの説明:

destを比較値と比較し、それらが一致する場合は、交換価値destに割り当てます。

これはアトミック操作であり、操作の実行中に他のプロセッサがdestの値を変更できないことを意味します。

アトミック操作なしで発生する可能性のある典型的な問題は、ここにリストされています、「ABA問題」

http://en.wikipedia.org/wiki/ABA_problem

なぜCAS関数を使用するのですか?

簡単な例はカウンターです。複数のスレッドでカウンターをインクリメントする場合は、インクリメントプロセスの機能を検討してください。

int i;
read the value of i
add one to the current value
save the value back to i.

このプロセッサが完了する前に、別のプロセッサがiの値を読み取り、i + 1を保存するとどうなりますか?

最終的に、 i+2ではなくi+1になります。

于 2011-08-24T04:13:48.957 に答える
1

ここにいくつかの解釈があります

  • おっととは何ですか、なぜそれらを圧縮する必要がありますか?


HotSpot用語の「oop」または「通常のオブジェクトポインタ」は、オブジェクトへの管理されたポインタです。これは通常、ネイティブマシンポインタと同じサイズです。つまり、LP64システムでは64ビットです。ILP32システムでは、最大ヒープサイズが4Gb未満であり、多くのアプリケーションには不十分です。

  • どのおっとが圧縮されていますか?

ILP32モードのJVMの場合、またはLP64モードでUseCompressedOopsフラグがオフになっている場合、すべてのoopsはネイティブマシンのワードサイズです。

UseCompressedOopsがtrueの場合、ヒープ内の次のoopsが圧縮されます。

•すべてのオブジェクトのklassフィールド•すべてのoopインスタンスフィールド•oop配列のすべての要素(objArray)

詳細については、この太陽のwikiを調べてください

于 2011-08-25T05:00:09.363 に答える