飞道的博客

Hotspot Thread本地方法实现 源码解析

223人阅读  评论(0)

   目录

1、start

2、join

3、sleep

4、interrupt / interrupted

5、yeild

6、holdsLock

7、setPriority


     Java中操作线程都是通过Thread的API来实现,其中核心逻辑都封装在本地方法中,其实现在jdk\src\share\native\java\lang\Thread.c中,部分方法如将当前线程置为悬浮状态的suspend,从悬浮状态恢复正常执行的resume方法和停止线程执行的stop方法都被标记成过时方法,本篇博客就不关注了,重点探讨其他的常用方法的实现细节。

1、start

     start方法用于创建一个关联的本地线程并启动该线程的执行,其实现如下:

public synchronized void start() {
        //0表示状态是NEW,如果不是0则抛出异常
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        //通知所属的ThreadGroup该线程启动执行了,ThreadGroup本身维护了已启动线程的数组和计数
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    //增加未启动线程计数,将其从已启动数组中移除
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
               //启动失败本身会抛出异常给调用方
            }
        }
    }

void add(Thread t) {
        synchronized (this) {
            if (destroyed) {
                throw new IllegalThreadStateException();
            }
            //threads是一个数组,维护所有已启动的线程
            if (threads == null) {
                threads = new Thread[4];
            } else if (nthreads == threads.length) {
                //如果threads满了,则扩容一倍
                threads = Arrays.copyOf(threads, nthreads * 2);
            }
            //保存t
            threads[nthreads] = t;
            //已启动线程数加1
            nthreads++;
            //未启动线程数减1,执行Thread的构造方法时会将该计数加1
            nUnstartedThreads--;
        }
    }

 void threadStartFailed(Thread t) {
        synchronized(this) {
            //从threads数组中移除
            remove(t);
            //未启动线程数加1
            nUnstartedThreads++;
        }
    }

private void remove(Thread t) {
        synchronized (this) {
            if (destroyed) {
                return;
            }
            for (int i = 0 ; i < nthreads ; i++) {
                if (threads[i] == t) {
                    //将i以后的数组元素整体往前挪一位
                    System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
                    //nthreads对应的数组元素置为NULL
                    threads[nthreads] = null;
                    break;
                }
            }
        }
    }

start0就是一个本地方法,会给当前Thread实例创建一个C++ JavaThread实例和OSThread实例,前者是线程在JVM中的表示,后者表示底层操作系统的原生线程,这三个都是一对一关系,Thread实例和JavaThread,JavaThread和OSThread都保存了彼此的引用。创建并初始化完成后,会设置OSThread的优先级,栈帧大小等属性,然后启动OSThread执行JavaThread的run方法,该方法会执行Thread实例的run方法。注意如果重复调用start方法或者因为内存不足导致OSThread创建失败都会抛出异常,其实现如下:

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  JavaThread *native_thread = NULL;
  bool throw_illegal_thread_state = false;

  {
    //获取锁
    MutexLocker mu(Threads_lock);

    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
      //如果关联的JavaThread不为空,说明该线程已经启动过,需要抛出异常
      throw_illegal_thread_state = true;
    } else {
      //获取stackSize属性,1.4以上不是从Thread实例中读取,直接返回0
      jlong size =
             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
      
      size_t sz = size > 0 ? (size_t) size : 0;
      //创建JavaThread和关联的OSThread
      native_thread = new JavaThread(&thread_entry, sz);

      if (native_thread->osthread() != NULL) {
        //osthread不为空,prepare方法会建立Java Thread实例同JavaThread之间的关联关系
        //并将Java线程的优先级映射成原生线程的优先级并设置
        native_thread->prepare(jthread);
      }
    }
  }

  if (throw_illegal_thread_state) {
    //关联的JavaThread不为空,抛出异常
    THROW(vmSymbols::java_lang_IllegalThreadStateException());
  }

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

  if (native_thread->osthread() == NULL) {
    //创建osthread失败,抛出异常
    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

//获取eetop属性,该属性是一个long类型,保存关联的JavaThread指针
JavaThread* java_lang_Thread::thread(oop java_thread) {
  return (JavaThread*)java_thread->address_field(_eetop_offset);
}

jlong java_lang_Thread::stackSize(oop java_thread) {
  //获取stackSize属性
  if (_stackSize_offset > 0) {
    //只有1.4才会读取
    assert(JDK_Version::is_gte_jdk14x_version(), "sanity check");
    return java_thread->long_field(_stackSize_offset);
  } else {
    return 0;
  }
}

static void thread_entry(JavaThread* thread, TRAPS) {
  HandleMark hm(THREAD);
  Handle obj(THREAD, thread->threadObj());
  JavaValue result(T_VOID);
  //调用Thread的run方法
  JavaCalls::call_virtual(&result,
                          obj,
                          KlassHandle(THREAD, SystemDictionary::Thread_klass()),
                          vmSymbols::run_method_name(),
                          vmSymbols::void_method_signature(),
                          THREAD);
}


JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
  Thread() //Thread的构造方法就是初始化Thread的各属性
{
  if (TraceThreadEvents) {
    tty->print_cr("creating thread %p", this);
  }
  //初始化JavaThread自有的各种属性
  initialize();
  _jni_attach_state = _not_attaching_via_jni;
  //entry_point就是执行的run方法
  set_entry_point(entry_point);
  os::ThreadType thr_type = os::java_thread;
  //是否编译线程,编译线程也是JavaThread,但是对应的os::ThreadType类型不同
  thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :
                                                     os::java_thread;
  //创建一个原生线程,底层通过pthread_create创建,创建成功后将其设置到Thread的_osthread属性中,然后等待其初始化完成
  //,初始化结束后在startThread_lock上等待被唤醒
  //如果内存不足导致创建失败,则该属性为NULL
  os::create_thread(this, thr_type, stack_sz);
}

//prio默认是NoPriority
void JavaThread::prepare(jobject jni_thread, ThreadPriority prio) {

  assert(Threads_lock->owner() == Thread::current(), "must have threads lock");
  
  Handle thread_oop(Thread::current(),
                    JNIHandles::resolve_non_null(jni_thread));
  assert(InstanceKlass::cast(thread_oop->klass())->is_linked(),
    "must be initialized");
  //保存关联的Java Thread实例
  set_threadObj(thread_oop());
  //设置Java Thread实例的eetop属性,保存当前JavaThread指针
  java_lang_Thread::set_thread(thread_oop(), this);

  if (prio == NoPriority) {
    //获取priority属性
    prio = java_lang_Thread::priority(thread_oop());
    assert(prio != NoPriority, "A valid priority should be present");
  }

  //将Java线程优先级映射成原生线程优先级,然后设置原生线程的优先级
  Thread::set_priority(this, prio);

  prepare_ext();

  // Add the new thread to the Threads list and set it in motion.
  // We must have threads lock in order to call Threads::add.
  // It is crucial that we do not block before the thread is
  // added to the Threads list for if a GC happens, then the java_thread oop
  // will not be visited by GC.
  Threads::add(this);
}

void set_threadObj(oop p)                      { _threadObj = p; }

//设置eetop属性
void java_lang_Thread::set_thread(oop java_thread, JavaThread* thread) {
  java_thread->address_field_put(_eetop_offset, (address)thread);
}

//获取priority属性,默认是继承父线程的的线程优先级
ThreadPriority java_lang_Thread::priority(oop java_thread) {
  return (ThreadPriority)java_thread->int_field(_priority_offset);
}

void Thread::set_priority(Thread* thread, ThreadPriority priority) {
  trace("set priority", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  //设置线程优先级
  (void)os::set_priority(thread, priority);
}

OSReturn os::set_priority(Thread* thread, ThreadPriority p) {
  if (p >= MinPriority && p <= MaxPriority) {
    //将Java的优先级映射成原生线程的优先级
    int priority = java_to_os_priority[p];
    return set_native_priority(thread, priority);
  } else {
    assert(false, "Should not happen");
    return OS_ERR;
  }
}

//force_daemon默认为false
void Threads::add(JavaThread* p, bool force_daemon) {
  // The threads lock must be owned at this point
  assert_locked_or_safepoint(Threads_lock);

  // 初始化GC相关的队列
  p->initialize_queues();
  //插入到thread_list链表中
  p->set_next(_thread_list);
  _thread_list = p;
  _number_of_threads++;
  oop threadObj = p->threadObj();
  bool daemon = true;
  
  if ((!force_daemon) && (threadObj == NULL || !java_lang_Thread::is_daemon(threadObj))) {
    //非daemon线程计数加1
    _number_of_non_daemon_threads++;
    daemon = false;
  }
  //ThreadService维护的相关计数加1
  ThreadService::add_thread(p, daemon);

  Events::log(p, "Thread added: " INTPTR_FORMAT, p);
}

bool java_lang_Thread::is_daemon(oop java_thread) {
  return java_thread->bool_field(_daemon_offset) != 0;
}

void Thread::start(Thread* thread) {
  trace("start", thread);
  //DisableStartThread默认是false
  if (!DisableStartThread) {
    if (thread->is_Java_thread()) {
      //如果是java线程,设置线程状态
      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
                                          java_lang_Thread::RUNNABLE);
    }
    //启动原生线程
    os::start_thread(thread);
  }
}

void os::start_thread(Thread* thread) {
  MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
  OSThread* osthread = thread->osthread();
  osthread->set_state(RUNNABLE);
  //唤醒之前创建的在startThread_lock上等待的子线程,开始执行JavaThread的run方法
  pd_start_thread(thread);
}

void os::pd_start_thread(Thread* thread) {
  OSThread * osthread = thread->osthread();
  assert(osthread->get_state() != INITIALIZED, "just checking");
  //唤醒在startThread_lock上等待的线程
  Monitor* sync_with_child = osthread->startThread_lock();
  MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
  sync_with_child->notify();
}

 OSThread的具体执行逻辑就是在调用pthread_create函数时传入的java_start函数,该函数会负责初始化OSThread,初始化完成将状态设置为INITIALIZED并唤醒startThread_lock上等待的负责创建OSThread的线程,然后继续等待直到OSThread的状态不再是INITIALIZED。这时创建OSThread的线程发现OSThread已经初始化完成就会退出OSThread的创建方法,然后进入启动OSThread执行的方法,该方法将状态置为RUNNABLE,并唤醒startThread_lock等待的线程。这是创建的子线程就会开始正常执行,调用JavaThread的run方法,该方法的实现如下:

void JavaThread::run() {
  //初始TLAB
  this->initialize_tlab();

  //记录栈基地址
  this->record_base_of_stack_pointer();

  //初始化OSThread的栈帧
  this->record_stack_base_and_size();

  //初始化ThreadLocalStorage
  this->initialize_thread_local_storage();
  //创建stack_guard_pages
  this->create_stack_guard_pages();
  //空实现
  this->cache_global_variables();

  //修改线程状态,注意此时会检查是否进入安全点同步,如果是则阻塞当前线程
  ThreadStateTransition::transition_and_fence(this, _thread_new, _thread_in_vm);

  assert(JavaThread::current() == this, "sanity check");
  assert(!Thread::current()->owns_locks(), "sanity check");

  DTRACE_THREAD_PROBE(start, this);

  //设置JNIHandleBlock
  this->set_active_handles(JNIHandleBlock::allocate_block());

  if (JvmtiExport::should_post_thread_life()) {
    JvmtiExport::post_thread_start(this);
  }

  EventThreadStart event;
  if (event.should_commit()) {
     event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj()));
     event.commit();
  }

  //执行具体的run方法并在执行完成销毁当前实例
  thread_main_inner();

}

void JavaThread::thread_main_inner() {
  assert(JavaThread::current() == this, "sanity check");
  assert(this->threadObj() != NULL, "just checking");
  
  //如果没有待处理异常且没有被中止
  if (!this->has_pending_exception() &&
      !java_lang_Thread::is_stillborn(this->threadObj())) {
    {
      ResourceMark rm(this);
      this->set_native_thread_name(this->get_thread_name());
    }
    HandleMark hm(this);
    //执行entry_point函数,就是执行Thread的run方法
    this->entry_point()(this, this);
  }
  
  //run方法执行完成,准备退出线程
  this->exit(false);
  //释放JavaThread对应的内存
  delete this;
}

//stillborn表示线程是否被中止,调用stop方法时会将该属性置为true
bool java_lang_Thread::is_stillborn(oop java_thread) {
  return java_thread->bool_field(_stillborn_offset) != 0;
}

2、join

     join方法用于等待创建的线程执行完成并退出,该方法有三个版本,一个是无参数的,表示无期限等待,一个是有一个参数,指定等待的毫秒数,一个是有两个参数,指定等待的毫秒数和纳秒数,其实现如下:

public final void join() throws InterruptedException {
        join(0);
}

public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            //参数非法
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
           //isAlive是一个本地方法
            while (isAlive()) {
                //无期限等待
                wait(0);
            }
        } else {
            while (isAlive()) {
                //now初始是0
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                //被唤醒后更新now,表示已等待的时间
                now = System.currentTimeMillis() - base;
            }
        }
    }

public final synchronized void join(long millis, int nanos)
    throws InterruptedException {

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
        //实际没有处理纳秒,还是将其四舍五入成毫秒了
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }

注意join方法是synchronized方法,当Java线程退出的时候会在JavaThread::exit方法中调用ObjectLocker的notify_all方法,唤醒所有在该Thread实例关联的重量级锁上等待的线程,即调用join方法的线程,该方法的实现如下:

 其调用链如下:

调用join方法的线程判断目标线程不存在了就会终止while循环,退出join方法。判断Java线程是否存活的本地方法isAlive的实现如下:

JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_IsThreadAlive");
  //从JNI引用中解析出对应的Thread实例oop
  oop thread_oop = JNIHandles::resolve_non_null(jthread);
  return java_lang_Thread::is_alive(thread_oop);
JVM_END

bool java_lang_Thread::is_alive(oop java_thread) {
  //获取关联的JavaThread,如果为NULL表示该线程已经退出
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  return (thr != NULL);
}

//在调用ObjectLocker的notify_all方法前会将该属性置为NULL
JavaThread* java_lang_Thread::thread(oop java_thread) {
  return (JavaThread*)java_thread->address_field(_eetop_offset);
}

 用于设置eetop属性的set_thread方法的调用链如下:

其中prepare是线程启动时调用的,ensure_join是线程退出时调用的,该方法的实现如下:

static void ensure_join(JavaThread* thread) {
  Handle threadObj(thread, thread->threadObj());
  assert(threadObj.not_null(), "java thread object must exist");
  //创建ObjectLocker
  ObjectLocker lock(threadObj, thread);
  //清除待处理异常,因为线程准备退出了
  thread->clear_pending_exception();
  //设置线程状态为TERMINATED
  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
  //将eetop属性置为NULL,这样is_alive方法就会返回false
  java_lang_Thread::set_thread(threadObj(), NULL);
  //唤醒所有在该thread oop关联的重量级锁上等待的线程
  lock.notify_all(thread);
  //清除待处理异常
  thread->clear_pending_exception();
}

3、sleep

      sleep是让当前线程休眠,有两个版本,一个指定休眠的毫秒数,一个指定休眠的毫秒数和纳秒数,同join方法,纳秒数实际会四舍五入成毫秒数,最终都是调用第一个版本,该方法是一个本地方法,其实现如下:

JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
  JVMWrapper("JVM_Sleep");

  if (millis < 0) {
    //参数异常
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
  }

  if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) {
    //如果已经被中断则抛出异常
    THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
  }

  //增加线程sleep的次数,并启动计入sleep耗时的计时器
  JavaThreadSleepState jtss(thread);

  EventThreadSleep event;

  if (millis == 0) {
    //x86下ConvertSleepToYield为true
    if (ConvertSleepToYield) {
      os::yield();
    } else {
      ThreadState old_state = thread->osthread()->get_state();
      thread->osthread()->set_state(SLEEPING);
      os::sleep(thread, MinSleepInterval, false);
      thread->osthread()->set_state(old_state);
    }
  } else {
    ThreadState old_state = thread->osthread()->get_state();
    //将osthread的状态置为SLEEPING
    thread->osthread()->set_state(SLEEPING);
    if (os::sleep(thread, millis, true) == OS_INTRPT) {
      if (!HAS_PENDING_EXCEPTION) {
        //sleep被中断了
        if (event.should_commit()) {
          //发布事件
          event.set_time(millis);
          event.commit();
        }
        //抛出异常
        THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
      }
    }
    //恢复原来的状态
    thread->osthread()->set_state(old_state);
  }
  if (event.should_commit()) {
    event.set_time(millis);
    event.commit();
  }
JVM_END

//返回当前线程是否已经被中断
bool Thread::is_interrupted(Thread* thread, bool clear_interrupted) {
  trace("is_interrupted", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  return os::is_interrupted(thread, clear_interrupted);
}

bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
    "possibility of dangling Thread pointer");

  OSThread* osthread = thread->osthread();
  bool interrupted = osthread->interrupted();
  if (interrupted && clear_interrupted) {
    //如果需要清除interrupted标识
    osthread->set_interrupted(false);
  }

  return interrupted;
}

int os::sleep(Thread* thread, jlong millis, bool interruptible) {
  assert(thread == Thread::current(),  "thread consistency check");

  ParkEvent * const slp = thread->_SleepEvent ;
  slp->reset() ;
  OrderAccess::fence() ;

  if (interruptible) {
    jlong prevtime = javaTimeNanos();

    for (;;) {
      if (os::is_interrupted(thread, true)) {
        //如果线程已被中断
        return OS_INTRPT;
      }

      jlong newtime = javaTimeNanos();

      if (newtime - prevtime < 0) {
        //linux不支持monotonic_clock
        assert(!Linux::supports_monotonic_clock(), "time moving backwards");
      } else {
        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
      }

      if(millis <= 0) {
        //休眠的时间已过
        return OS_OK;
      }

      prevtime = newtime;

      {
        assert(thread->is_Java_thread(), "sanity check");
        JavaThread *jt = (JavaThread *) thread;
        //修改线程状态为_thread_blocked,等代码块退出将其恢复成_thread_in_vm,转换过程中会检查安全点
        ThreadBlockInVM tbivm(jt);
        //将OSThread的状态修改为CONDVAR_WAIT,代码块退出时恢复原来的状态
        OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);

        jt->set_suspend_equivalent();
        //让当前线程休眠,如果线程被唤醒了则继续for循环
        slp->park(millis);

        jt->check_and_wait_while_suspended();
      }
    }
  } else {
    OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
    jlong prevtime = javaTimeNanos();
    
    //逻辑同上只是不需要检查目标线程是否中断,使用与sleep时间特别短的情形,如sleep(0)
    for (;;) {
      
      jlong newtime = javaTimeNanos();

      if (newtime - prevtime < 0) {
        assert(!Linux::supports_monotonic_clock(), "time moving backwards");
      } else {
        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
      }

      if(millis <= 0) break ;

      prevtime = newtime;
      slp->park(millis);
    }
    return OS_OK ;
  }
}

其中JavaThreadSleepState通过构造和析构函数来统计线程休眠的次数和累计时间,其定义如下:

4、interrupt / interrupted

     interrupt方法用于中断某个处于阻塞状态的线程,如调用sleep方法后被阻塞的线程,中断后该线程就会抛出InterruptedException异常;interrupted方法用于判断某个线程是否被中断了,其实现如下:

public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();
        
        //blockerLock就是操作blocker的锁
        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                //可中断IO在开始执行IO前会设置blocker,正常情形下为null
                interrupt0();           // Just to set the interrupt flag
                //调用其interrupt方法
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

public static boolean interrupted() {
    //currentThread和isInterrupted都是本地方法
    return currentThread().isInterrupted(true);
}

  搜索Interruptible接口的实现类,如下:

这两个都是用匿名内部类实现的该接口,以AbstractSelector为例说明,其实现如下:

其中blockedOn方法会调用Thread类的blockedOn来设置blocker属性,其实现如下:

该方法只能在包内访问,不是public的,所以AbstractInterruptibleChannel的blockedOn借助了sun的特殊方法,其实现如下:

currentThread,isInterrupted和interrupt0三个本地方法的实现如下:

JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
  JVMWrapper("JVM_CurrentThread");
  //thread是JVM_ENTRY中获取的,获取其关联的Thread实例oop
  oop jthread = thread->threadObj();
  assert (thread != NULL, "no current thread!");
  //返回该实例oop,注意需要将其包裹成JNI本地引用
  return JNIHandles::make_local(env, jthread);
JVM_END

#define JVM_ENTRY(result_type, header)                               \
extern "C" {                                                         \
  result_type JNICALL header {                                       \
    //从JNIEnv中获取当前的JavaThread指针
    JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
    //切换线程状态,需要检查安全点
    ThreadInVMfromNative __tiv(thread);                              \
    debug_only(VMNativeEntryWrapper __vew;)                          \
    VM_ENTRY_BASE(result_type, header, thread)

static JavaThread* thread_from_jni_environment(JNIEnv* env) {
    //每个JavaThread都有一个单独的JNIEnv实例,此处是根据env的地址和其在JavaThread中的属性偏移量倒推出JavaThread的地址
    JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset()));
    if (thread_from_jni_env->is_terminated()) {
       //如果JVM正在退出的过程中,则阻塞当前线程
       thread_from_jni_env->block_if_vm_exited();
       //返回NULL
       return NULL;
    } else {
       return thread_from_jni_env;
    }
  }

JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted))
  JVMWrapper("JVM_IsInterrupted");

  //获取对应的Thread实例
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  //如果就是当前线程,则不需要获取锁,否则需要获取Threads_lock锁
  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
  //获取关联的JavaThread
  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
  if (thr == NULL) {
    return JNI_FALSE;
  } else {
    //JavaThread不为空,判断其是否被中断,clear_interrupted默认为true,此处就是1
    return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0);
  }
JVM_END

JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_Interrupt");

  //获取对应的Thread实例
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  //如果就是当前线程,则不需要获取锁,否则需要获取Threads_lock锁
  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
  //获取关联的JavaThread
  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
  if (thr != NULL) {
    Thread::interrupt(thr);
  }
JVM_END

void Thread::interrupt(Thread* thread) {
  trace("interrupt", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  os::interrupt(thread);
}

void os::interrupt(Thread* thread) {
  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
    "possibility of dangling Thread pointer");

  OSThread* osthread = thread->osthread();

  if (!osthread->interrupted()) {
    //将interrupted标识置为true
    osthread->set_interrupted(true);
    OrderAccess::fence();
    ParkEvent * const slp = thread->_SleepEvent ;
    //唤醒在_SleepEvent上等待的线程,_SleepEvent用于实现线程sleep
    if (slp != NULL) slp->unpark() ;
  }

  //唤醒在parker上等待的线程,parker用于实现Unsafe的park和unpark方法
  if (thread->is_Java_thread())
    ((JavaThread*)thread)->parker()->unpark();

  ParkEvent * ev = thread->_ParkEvent ;
  //唤醒在_ParkEvent上等待的线程,_ParkEvent用于实现synchronized关键字
  if (ev != NULL) ev->unpark() ;

}

从上述实现可知,interrupt方法会将OSThread的中断标识置为true,同时唤醒在因为sleep、synchronized关键字或者Java的Lock锁而阻塞等待的线程,注意该方法并不会如字面所说的会中断正在执行中的线程。

5、yeild

      yeild就是一个本地方法,用于让出当前线程的CPU时间片,其实现如下:

JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))
  JVMWrapper("JVM_Yield");
  //如果操作系统不支持yeild则返回
  if (os::dont_yield()) return;
  //ConvertYieldToSleep默认为false
  if (ConvertYieldToSleep) {
    os::sleep(thread, MinSleepInterval, false);
  } else {
    os::yield();
  }
JVM_END

void os::yield() {
  //sched_yield()是Linux的API,会让出当前线程的CPU占有权,然后把线程放到调度队列的尾端,即优先调度其他的线程
  //给他们分配CPU时间片
  sched_yield();
}

6、holdsLock

     holdsLock是一个本地方法,用于判断当前线程是否持有某个对象的锁,其实现如下:

JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj))
  JVMWrapper("JVM_HoldsLock");
  assert(THREAD->is_Java_thread(), "sanity check");
  if (obj == NULL) {
    //obj为空抛出异常
    THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
  }
  Handle h_obj(THREAD, JNIHandles::resolve(obj));
  return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj);
JVM_END

bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
                                                   Handle h_obj) {
  if (UseBiasedLocking) {
    //撤销偏向锁,如果该偏向锁正在使用,则会被升级成轻量级锁
    BiasedLocking::revoke_and_rebias(h_obj, false, thread);
    assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
  }

  assert(thread == JavaThread::current(), "Can only be called on current thread");
  oop obj = h_obj();
  
  //获取对象头,如果正在锁膨胀,则通过自旋,yeild,park等方式等待锁膨胀完成
  markOop mark = ReadStableMark (obj) ;

  if (mark->has_locker()) {
    //如果是轻量级锁状态,则判断对象头包含的locker是否属于当前线程
    return thread->is_lock_owned((address)mark->locker());
  }
  if (mark->has_monitor()) {
    //如果是重量级锁,则判断owner属性是否是当前线程指针
    ObjectMonitor* monitor = mark->monitor();
    return monitor->is_entered(thread) != 0 ;
  }
  //无锁状态
  assert(mark->is_neutral(), "sanity check");
  return false;
}

inline intptr_t ObjectMonitor::is_entered(TRAPS) const {
  if (THREAD == _owner || THREAD->is_lock_owned((address) _owner)) {
    return 1;
  }
  return 0;
}

7、setPriority

    setPriority用于设置线程的优先级,其实现如下:

public final void setPriority(int newPriority) {                        
    ThreadGroup g;                                                      
    checkAccess();                                                      
    if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {    
       //参数非法 
        throw new IllegalArgumentException();                           
    }                                                                   
    if((g = getThreadGroup()) != null) {                                
        if (newPriority > g.getMaxPriority()) {
            //不能超过线程组的最高优先级                         
            newPriority = g.getMaxPriority();                           
        } 
        //修改priority属性并调用setPriority0方法                                             
        setPriority0(priority = newPriority);                           
    }                                                                   
}                                                                       

 JavaThread定义的线程优先级枚举常量如下:

setPriority0是一个本地方法,其实现如下:

JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
  JVMWrapper("JVM_SetThreadPriority");
  //获取Threads_lock锁
  MutexLocker ml(Threads_lock);
  //获取关联的Thread实例oop
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  //设置Thread实例的priority属性
  java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
  //获取关联的JavaThread实例
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  if (thr != NULL) {                  // Thread not yet started; priority pushed down when it is
    //设置优先级
    Thread::set_priority(thr, (ThreadPriority)prio);
  }
JVM_END

void java_lang_Thread::set_priority(oop java_thread, ThreadPriority priority) {
  java_thread->int_field_put(_priority_offset, priority);
}

 设置OSThread的线程优先级前会将Java线程的优先级映射成OSThread的线程优先级,其映射关系如下:

Java线程的优先级就是上面数组的索引,比如NormPriority对应的OSThread的优先级就是0。

Java线程的优先级默认情况是继承自父线程的优先级,那么第一个创建的main线程的优先级是啥了?参考JVM启动过程中用于创建main线程的create_initial_thread方法的实现,如下:

static oop create_initial_thread(Handle thread_group, JavaThread* thread, TRAPS) {
  //加载并初始化java_lang_Thread类
  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
  instanceKlassHandle klass (THREAD, k);
  //分配一个instanceHandle
  instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
  
  //Thread实例oop保存关联的JavaThread
  java_lang_Thread::set_thread(thread_oop(), thread);
  //设置线程优先级为NormPriority
  java_lang_Thread::set_priority(thread_oop(), NormPriority);
  //JavaThread保存关联的Thread实例oop
  thread->set_threadObj(thread_oop());
  
  //初始化一个字符串main
  Handle string = java_lang_String::create_from_str("main", CHECK_NULL);

  JavaValue result(T_VOID);
  //调用Thread的构造方法,创建的Thread实例保存在thread_oop中
  JavaCalls::call_special(&result, thread_oop,
                                   klass,
                                   vmSymbols::object_initializer_name(),
                                   vmSymbols::threadgroup_string_void_signature(),
                                   thread_group,
                                   string,
                                   CHECK_NULL);
  return thread_oop();
}

 main线程的优先级就是NormPriority,由该线程创建的子线程的优先级就默认是NormPriority。


转载:https://blog.csdn.net/qq_31865983/article/details/105174567
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场