Javaの並行処理シリーズ - スレッド起動プロセスのJVMの深い理解

序文

最近同時から開始する準備ができて、トピックを開くのが好きnotes'd整理。同時ピースと、開始AQSの思考を開始する場所から、自分自身、新しいアイデアを持っているを終了する前に、OpenJDKのデバッグ時間をコンパイルしたノートのいくつかを見るために起こった、最も基本的なスタートで始まり、これを送信することを決定しましたないスレッド、そして私たちは、JDKを組み合わせて、ホットスポットは、探検どのようなスレッドのインとアウト。
スレッド定義:最小単位の実行中は、プロセスに含まれています。

Javaでのスレッド

class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
    ...//省略一大波代码,和一些英文注释
    public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

通常、我々はスタートのスレッドが()メソッドと呼ばれている使用しています。
私たちはstart()メソッドを見ることができる上記のスレッドのソース構造から
新しい状態が、ない場合は、例外スレッド状態を投げるかどうかを判断するために、
次に実行START0を() ;これは、ローカル方法であります

JVM定義されたスレッド

のは、JDKのローカルOpenJDKのオープンメソッドの定義を見てみましょう、オープンThread.c

#include "jni.h"
#include "jvm.h"

#include "java_lang_Thread.h"

#define THD "Ljava/lang/Thread;"
#define OBJ "Ljava/lang/Object;"
#define STE "Ljava/lang/StackTraceElement;"
#define STR "Ljava/lang/String;"

#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))

static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

#undef THD
#undef OBJ
#undef STE
#undef STR

JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}

;上記のコードJNI関連に登録されている説明1の背後に必要があれば、それは、非常に簡単です
聞かせてのは、対応するJVMをSTART0する方法を見つける、JVM_StartThread
jvm.cppで

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  JavaThread *native_thread = NULL;
  // Heap_lock while we construct the exception.
  bool throw_illegal_thread_state = false;

  {
    MutexLocker mu(Threads_lock);

    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
      throw_illegal_thread_state = true;
    } else {
      // We could also check the stillborn flag to see if this thread was already stopped, but
      // for historical reasons we let the thread detect that itself when it starts running

      jlong size =
             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
      size_t sz = size > 0 ? (size_t) size : 0;
      native_thread = new JavaThread(&thread_entry, sz);

      if (native_thread->osthread() != NULL) {
        // Note: the current thread is not being used within "prepare".
        native_thread->prepare(jthread);
      }
    }
  }

  if (throw_illegal_thread_state) {
    THROW(vmSymbols::java_lang_IllegalThreadStateException());
  }

  assert(native_thread != NULL, "Starting null thread?");

  if (native_thread->osthread() == NULL) {
    // No one should hold a reference to the 'native_thread'.
    delete native_thread;
    if (JvmtiExport::should_post_resource_exhausted()) {
      JvmtiExport::post_resource_exhausted(
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
        "unable to create new native thread");
    }
    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
              "unable to create new native thread");
  }

  Thread::start(native_thread);

JVM_END

これらは、メインロジックは、我々はステップ分析によってステップを行っています

まず、ミューテックスのロックを取得

MutexLocker mu(Threads_lock);

状態が起動しないことを保証するために、スレッドの状態をチェックしてください

 if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
      throw_illegal_thread_state = true;

以前のチェックは、デバイスは、主に、コンストラクタによって達成JavaThreadのJVMを作成し

native_thread = new JavaThread(&thread_entry, sz);

このコンストラクタの主な内容を見てください

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
  Thread()
  ...//省略
{
  if (TraceThreadEvents) {
    tty->print_cr("creating thread %p", this);
  }
  initialize();
  _jni_attach_state = _not_attaching_via_jni;
  set_entry_point(entry_point);
  // Create the native thread itself.
  // %note runtime_23
  os::ThreadType thr_type = os::java_thread;
  thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :
                                                     os::java_thread;
  os::create_thread(this, thr_type, stack_sz);

私たちは、最後の行のOS :: create_thread(これ、thr_type、stack_sz)を参照してください。これは、スレッドの作成、実際のシステムレベルにマッピングされています。

bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
  assert(thread->osthread() == NULL, "caller responsible");

  // Allocate the OSThread object
  OSThread* osthread = new OSThread(NULL, NULL);
  if (osthread == NULL) {
    return false;
  }

  // set the correct thread state
  osthread->set_thread_type(thr_type);

  // Initial state is ALLOCATED but not INITIALIZED
  osthread->set_state(ALLOCATED);

  thread->set_osthread(osthread);
  ......//省略
    pthread_t tid;
    int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

    pthread_attr_destroy(&attr);

    if (ret != 0) {
      if (PrintMiscellaneous && (Verbose || WizardMode)) {
        perror("pthread_create()");
      }
      // Need to clean up stuff we've allocated so far
      thread->set_osthread(NULL);
      delete osthread;
      if (lock) os::Linux::createThread_lock()->unlock();
      return false;
    }

    // Store pthread info into the OSThread
    osthread->set_pthread_id(tid);

OSレベルのスレッドを作成し、JavaThreadが結合した、次のドローフォーカス

int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

java_startが新たにスレッド開始エントリを作成され、それは()メソッド、でJavaを実行して起動するための信号を待つことになる
次のようにJVMの実装固有のロジックコード

  // wait until os::start_thread()
    while (osthread->get_state() == INITIALIZED) {
      sync->wait(Mutex::_no_safepoint_check_flag);
    }
  }

  // call one more level start routine
  thread->run()

結合スレッドのJavaスレッドとJVMで、ならびにシステムレベルのスレッドが結合を有する前のステップ;次戻るJVM_StartThread方法、スレッドが作成され、(jthread)調製native_thread->呼び出します。

最後に、実際に始めたスレッド

Thread::start(native_thread);

次のように層によって、OSレベルのスレッド層への呼び出しでもある、特定の論理があります

void os::start_thread(Thread* thread) {
  // guard suspend/resume
  MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
  OSThread* osthread = thread->osthread();
  osthread->set_state(RUNNABLE);
  pd_start_thread(thread);
}

この時点で、私たちは本当に論理スレッドがあって、もちろん、まだいくつかの詳細システムを呼び出します。このように、我々はJavaレベル、JVMレベル、OSレベルの関係にスレッド全体を把握することができる、でも、その後の記事では、同時シリーズプライマーも従うのは良い章では、知識の同時作品をお話していきます。

私はまた、より多くのコンテンツ用に調整され、個々のサイトが心配です:https://jie3615.github.io/


この記事は、転載することを歓迎し、著者と共同所有の庭のブログに属しているが、この節で宣言され、著者の同意なしに保持され、記事ページの見かけ上の位置にある元の接続、法的責任を追及するそうでない場合は権利を与えられなければなりません。

おすすめ

転載: www.cnblogs.com/jie3615/p/11272468.html