[讨论] 请教一下如何控制JVM中的线程

michael9527 2012-02-06
看了一下tomcat,默认启动的时候所有线程优先级都是一样的,在我机器上(windows sp3)是prio=6
我觉得调整优先级可能不是太准。《java线程》那本书上说,不同的机器对线程调度完全不同,甚至你设置的级别可能就被直接忽略掉了。
RednaxelaFX 2012-02-06
在生产环境里用JDI API连接到目标JVM上同样会影响目标JVM的性能。
也有案例。正好AMD去年还是前天提交过一个patch去降低某些情况下在某些debugging功能未使用的时候连接一个JDI agent的开销。

在Oracle/Sun JDK里,JPDA的VirtualMachine.suspend()在底下用的是JVMTI的SuspendThread函数。

=================================================

这个是JVMTI的SuspendThread在HotSpot VM里的实现:
// Threads_lock NOT held, java_thread not protected by lock
// java_thread - pre-checked
jvmtiError
JvmtiEnv::SuspendThread(JavaThread* java_thread) {
  // don't allow hidden thread suspend request.
  if (java_thread->is_hidden_from_external_view()) {
    return (JVMTI_ERROR_NONE);
  }

  {
    MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
    if (java_thread->is_external_suspend()) {
      // don't allow nested external suspend requests.
      return (JVMTI_ERROR_THREAD_SUSPENDED);
    }
    if (java_thread->is_exiting()) { // thread is in the process of exiting
      return (JVMTI_ERROR_THREAD_NOT_ALIVE);
    }
    java_thread->set_external_suspend();
  }

  if (!JvmtiSuspendControl::suspend(java_thread)) {
    // the thread was in the process of exiting
    return (JVMTI_ERROR_THREAD_NOT_ALIVE);
  }
  return JVMTI_ERROR_NONE;
} /* end SuspendThread */

bool JvmtiSuspendControl::suspend(JavaThread *java_thread) {
  // external suspend should have caught suspending a thread twice

  // Immediate suspension required for JPDA back-end so JVMTI agent threads do
  // not deadlock due to later suspension on transitions while holding
  // raw monitors.  Passing true causes the immediate suspension.
  // java_suspend() will catch threads in the process of exiting
  // and will ignore them.
  java_thread->java_suspend();

  // It would be nice to have the following assertion in all the time,
  // but it is possible for a racing resume request to have resumed
  // this thread right after we suspended it. Temporarily enable this
  // assertion if you are chasing a different kind of bug.
  //
  // assert(java_lang_Thread::thread(java_thread->threadObj()) == NULL ||
  //   java_thread->is_being_ext_suspended(), "thread is not suspended");

  if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) {
    // check again because we can get delayed in java_suspend():
    // the thread is in process of exiting.
    return false;
  }

  return true;
}


而这个是java.lang.Thread.suspend()在HotSpot VM里的实现:
JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_SuspendThread");
  oop java_thread = JNIHandles::resolve_non_null(jthread);
  JavaThread* receiver = java_lang_Thread::thread(java_thread);

  if (receiver != NULL) {
    // thread has run and has not exited (still on threads list)

    {
      MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag);
      if (receiver->is_external_suspend()) {
        // Don't allow nested external suspend requests. We can't return
        // an error from this interface so just ignore the problem.
        return;
      }
      if (receiver->is_exiting()) { // thread is in the process of exiting
        return;
      }
      receiver->set_external_suspend();
    }

    // java_suspend() will catch threads in the process of exiting
    // and will ignore them.
    receiver->java_suspend();

    // It would be nice to have the following assertion in all the
    // time, but it is possible for a racing resume request to have
    // resumed this thread right after we suspended it. Temporarily
    // enable this assertion if you are chasing a different kind of
    // bug.
    //
    // assert(java_lang_Thread::thread(receiver->threadObj()) == NULL ||
    //   receiver->is_being_ext_suspended(), "thread is not suspended");
  }
JVM_END


也就是说在HotSpot VM里用于支持Java线程挂起的代码,在JVMTI的SuspendThread和在java.lang.Thread.suspend()本质上是一样的。对这个VM来说,这两种操作都是“外部请求挂起线程”,需要执行的调用都是set_external_suspend()与java_suspend()。

所以潜在的死锁问题也没有本质上的区别…
javas 2012-02-06
cpu resources control 如果不适合在java thread级别来做控制,其他语言或者平台是怎么实现?


另外问个问题:java里面为什么都是'当前线程'来resume/suspend/yield/stop?可否当前线程来stop另外一个线程来?




RednaxelaFX 2012-02-06
javas 写道
cpu resources control 如果不适合在java thread级别来做控制,其他语言或者平台是怎么实现?

如果用操作系统的原生线程,可以什么都不做,也就是交给操作系统。这样应用程序就只有很少的控制权,通常只能通过优先级来提示操作系统的调度器自己的线程应该如何调度;
或者是使用某种形式的green-thread并且完全自己写一个调度器。这样应用对线程调度的控制权最高,而代码的复杂度也最高,而且green-thread的某些基本操作容易比原生线程的慢。
两个极端的中间则有各种不同的取舍方式。例如说在Windows上有操作系统提供的原生Fiber,让用户可以自己写代码去调度这些Fiber;使用这个来实现green-thread比完全自己实现起来要容易一点点(但就不跨平台了)。

至于为什么不建议在Java里做这种事情…
well,如果一个团队通过做这样的事情能得到足够收益那做就做呗。只不过通常做Java开发的团队较少碰比较底层的东西(楼主的团队很明显就是这种情况),自己做很容易搞砸;其次,真的能带来足够收益么?


javas 写道
另外问个问题:java里面为什么都是'当前线程'来resume/suspend/yield/stop?可否当前线程来stop另外一个线程来?

上面的讨论一直都是以“某个线程的suspend()/resume()/stop()被别的线程调用”为前提的。你看漏了什么么?
以suspend()为例,
Thread t = ...
t.suspend();

如果t != Thread.currentThread(),那么在suspend()里会有安全性检查;而当t == Thread.currentThread()则不需要做这个检查。检查可以由security policy配置。除此之外并没有别的限制。
Global site tag (gtag.js) - Google Analytics