六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 64|回复: 0

Thread Management

[复制链接]

升级  49.33%

36

主题

36

主题

36

主题

秀才

Rank: 2

积分
124
 楼主| 发表于 2013-1-15 02:47:56 | 显示全部楼层 |阅读模式
From http://jikesrvm.org/Thread+Management
Thread Management

This section provides some explanation of how Java threads are scheduled and synchronized by Jikes RVM.
All Java threads (application threads, garbage collector threads, etc.) derive from RVMThread. Each RVMThreadmaps directly to one native thread, which may be implemented usingwhichever C/C++ threading library is in use (currently either pthreadsor Harmony threads). Unless -X:forceOneCPU is used, native threads areallowed to be arbitrarily scheduled by the OS using whatever processorresources are available; Jikes RVM does not attempt to control the thread-processor mapping at all.
Using native threading gives JikesRVM better compatibility for existing JNI code, as well as improvedperformance, and greater infrastructure simplicity. Scheduling isoffloaded entirely to the operating system; this is both what nativecode would expect and what maximizes the OS scheduler's ability tooptimally schedule Javathreads. As well, the resulting VM infrastructure is both simpler andmore robust, since instead of focusing on scheduling decisions it cantake a "hands-off" approach except when Java threads have to bepreempted for sampling, on-stack-replacement, garbage collection,Thread.suspend(), or locking. The main task of RVMThread and other code in org.jikesrvm.scheduler is thus to override OS scheduling decisions when the VM demands it.
The remainder of this section is organized as follows. Themanagement of a thread's state is discussed in detail. Mechanisms forblocking and handshaking threads are described. The VM's internallocking mechanism, the Monitor, is described.  Finally, the locking implementation is discussed.
<div class="section_2">Tracking the Thread State

The state of a thread is broken down into two elements:

  • Should the thread yield at a safe point?
  • Is the thread running Java code right now?
The first mechanism is provided by the RVMThread.takeYieldpointfield, which is 0 if the thread should not yield, or non-zero if itshould yield at the next safe point. Negative versus positive valuesindicate the type of safe point to yield at (epilogue/prologue, or any,respectively).
But this alone is insufficient to manage threads, as it relies onall threads being able to reach a safe point in a timely fashion. NewJava threads may be started at any time, including at the exact momentthat the garbage collector is starting; a starting-but-not-yet-startedthread may not reach a safe point if the thread that was starting it isalready blocked. Java threads may terminate at any time; terminatedthreads will never again reach a safe point. Any Java thread may callinto arbitrary JNI code, which is outside of the VM's control, and mayrun for an arbitrary amount of time without reaching a Java safe point.As well, other mechanisms of RVMThread may cause a thread toblock, thereby making it incapable of reaching a safe point in a timelyfashion. However, in each of these cases, the Java thread is"effectively safe" - it is not running Java code that would interferewith the garbage collector, on-stack-replacement, locking, or any otherJava runtime mechanism. Thus, a state management system is needed thatwould notify these runtime services when a thread is "effectively safe"and does not need to be waited on.
RVMThread provides for the following thread states, whichdescribe to other runtime services the state of a Java thread. Thesestates are designed with extreme care to support the following features:

  • Allow Java threads to either execute Java code, whichperiodically reaches safe points, and native code which is "effectivelysafe" by virtue of not having access to VM services.
  • Allowother threads (either Java threads or VM threads) to asynchronouslyrequest a Java thread to block. This overlaps with the takeYieldpoint mechanism, but adds the following feature: a thread that is "effectively safe" does not have to block.
  • Preventrace conditions on state changes. In particular, if a thread runningnative code transitions back to running Java code while some otherthread expects it to be either "effectively safe" or blocked at a safepoint, then it should block. As well, if we are waiting on some Javathread to reach a safe point but it instead escapes into running nativecode, then we would like to be notified that even though it is not at asafe point, it is not effectively safe, and thus, we do not have towait for it anymore.
The states used to put these features into effect are listed below.

  • NEW. This means that the thread has been created but is notstarted, and hence is not yet running. NEW threads are alwayseffectively safe, provided that they do not transition to any of theother states.
  • IN_JAVA. The thread is running Java code. Thisalmost always corresponds to the OS "runnable" state - i.e. the threadhas no reason to be blocked, is on the runnable queue, and if aprocessor becomes available it will execute, if it is not alreadyexecuting. IN_JAVA thread will periodically reach safe points at whichthe takeYieldpoint field will be tested. Hence, setting thisfield will ensure that the thread will yield in a timely fashion,unless it transitions into one of the other states in the meantime.
  • IN_NATIVE.  The thread is running either native C code, or internal VM code (which, by virtue of JikesRVM's metacircularity, may be written in Java). IN_NATIVE threads are"effectively safe" in that they will not do anything that interfereswith runtime services, at least until they transition into some otherstate. The IN_NATIVE state is most often used to denote threads thatare blocked, for example on a lock.
  • IN_JNI. The thread hascalled into JNI code. This is identical to the IN_NATIVE state in allways except one: IN_JNI threads have a JNIEnvironment thatstores more information about the thread's execution state (stackinformation, etc), while IN_NATIVE threads save only the minimum set ofinformation required for the GC to perform stack scanning.
  • IN_JAVA_TO_BLOCK.This represents a thread that is running Java code, as in IN_JAVA, buthas been requested to yield. In most cases, when you set takeYieldpointto non-zero, you will also change the state of the thread from IN_JAVAto IN_JAVA_TO_BLOCK. If you don't intend on waiting for the thread (forexample, in the case of sampling, where you're opportunisticallyrequesting a yield), then this step may be omitted; but in the cases oflocking and garbage collection, when a thread is requested to yieldusing takeYieldpoint, its state will also be changed.
  • BLOCKED_IN_NATIVE.BLOCKED_IN_NATIVE is to IN_NATIVE as IN_JAVA_TO_BLOCK is to IN_JAVA.When requesting a thread to yield, we check its state; if it'sIN_NATIVE, we set it to be BLOCKED_IN_NATIVE.
  • BLOCKED_IN_JNI.  Same as BLOCKED_IN_NATIVE, but for IN_JNI.
  • TERMINATED.  The thread has died.  It is "effectively safe", but will never again reach a safe point.
The states are stored in RVMThread.execStatus, an integerfield that may be rapidly manipulated using compare-and-swap. Thisfield uses a hybrid synchronization protocol, which includes bothcompare-and-swap and conventional locking (using the thread's Monitor, accessible via the RVMThread.monitor() method).  The rules are as follows:

  • All state changes except for IN_JAVA to IN_NATIVE or IN_JNI,and IN_NATIVE or IN_JNI back to IN_JAVA, must be done while holding thelock.
  • Only the thread itself can change its own state without holding the lock.
  • Theonly asynchronous state changes (changes to the state not done by thethread that owns it) that are allowed are IN_JAVA to IN_JAVA_TO_BLOCK,IN_NATIVE to BLOCKED_IN_NATIVE, and IN_JNI TO BLOCKED_IN_JNI.
The typical algorithm for requesting a thread to block looks as follows:
<div style="border-width: 1px;" class="code panel"><div class="codeContent panelContent">thread.monitor().lockNoHandshake();if (thread is running) {   thread.takeYieldpoint=1;   // transitions IN_JAVA -> IN_JAVA_TO_BLOCK, IN_NATIVE->BLOCKED_IN_NATIVE, etc.   thread.setBlockedExecStatus();       if (thread.isInJava()) {      // Thread will reach safe point soon, or else notify us that it left to native code.      // In either case, since we are holding the lock, the thread will effectively block      // on either the safe point or on the attempt to go to native code, since performing      // either state transition requires acquiring the lock, which we are now holding.   } else {      // Thread is in native code, and thus is "effectively safe", and cannot go back to      // running Java code so long as we hold the lock, since that state transition requires      // acquiring the lock.   }}thread.monitor().unlock();
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表