JVM Thread State

JVM线程状态与操作系统的线程状态。

JVM Thread State

虚拟机中线程状态并不是操作系统真实的线程状态。

Thread.State属于虚拟机状态,与系统线程状态没有任何关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*
* @since 1.5
* @see #getState
*/
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,

/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,

/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,

/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,

/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,

/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}

RUNNABLE状态需要注意一下,包含了就绪等待运行两种实际的运行情况。

BLOCKEDMonitor Lock有关。

WAITING/TIMED_WAITING也同样是基于Monitor实现。

1
2
3
4
5
6
7
8
9
class ObjectMonitor {
...
volatile markOop _header; // 对象头
void* volatile _object; // 关联对象
void * volatile _owner; // 锁的持有者
ObjectWaiter * volatile _EntryList ; // 阻塞线程列表
ObjectWaiter * volatile _WaitSet; // 调用wait()等待monitor的线程
...
};

Linux Process State

Linux仅有定义Process State,也就是进程状态,具体包含五个状态:

  • TASK_RUNNING(运行)
  • TASK_INTERRUPTIBLE(中断)
  • TASK_UNINTERUPTIBLE(不可中断)
  • _TASK_TRACED(跟踪)
  • _TASK_STOPPED(停止)

Java Thread yield

Thread.yield用于向调度器提示当前线程自愿让出处理器资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 /**
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
*
* <p> Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*
* <p> It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
*/
public static native void yield();

Thread.yield不会改变RUNNABLE的线程状态,只是会让出当前处理器进入就绪状态,等待下一次时间分片的分配执行。

openjdk jvm.cpp

1
2
3
4
5
6
7
8
9
10
11
JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))
JVMWrapper("JVM_Yield");
...
// When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.
// Critical for similar threading behaviour
if (ConvertYieldToSleep) {
os::sleep(thread, MinSleepInterval, false);
} else {
os::yield();
}
JVM_END

Java Thread join

Thread.join是让当前线程进入BLOCKED状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public final synchronized void join(long millis)
throws InterruptedException {
...
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
# 空转
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

从源码中可知,Thread.join是利用synchronizedMonitor来实现的线程的阻塞。

Java Thread sleep

Thread.sleep是让当前线程进入TIMED_WAITING状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;

下面是JVM中源码实现,

首先,调用thread->osthread()->set_state(SLEEPING),设置当前线程的状态,

然后,调用os::sleep(thread, millis, true),触发os::sleep功能。

os::sleep的大概流程:

  • 挂起进程(或线程)并修改其运行状态;
  • os::sleep提供的参数来设置一个定时器;
  • 当定时器会触发,内核收到中断后修改进程(或线程)的运行状态(进入就绪队列等待调度)。

openjdk jvm.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
JVMWrapper("JVM_Sleep");
...
// Save current thread state and restore it at the end of this block.
// And set new thread state to SLEEPING.
JavaThreadSleepState jtss(thread);

HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis);

if (millis == 0) {
// When ConvertSleepToYield is on, this matches the classic VM implementation of
// JVM_Sleep. Critical for similar threading behaviour (Win32)
// It appears that in certain GUI contexts, it may be beneficial to do a short sleep
// for SOLARIS
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();
thread->osthread()->set_state(SLEEPING);
if (os::sleep(thread, millis, true) == OS_INTRPT) {
// An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
// us while we were sleeping. We do not overwrite those.
if (!HAS_PENDING_EXCEPTION) {
HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1);
// TODO-FIXME: THROW_MSG returns which means we will not call set_state()
// to properly restore the thread state. That's likely wrong.
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
}
}
thread->osthread()->set_state(old_state);
}
HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0);
JVM_END

源码中SLEEPING状态对应着JVMTI状态如下,实际上就是State.TIMED_WAITING状态。

1
2
3
4
5
6
7
8
9
10
11
// Java Thread Status for JVMTI and M&M use.
// This thread status info is saved in threadStatus field of
// java.lang.Thread java class.
enum ThreadStatus {
...
SLEEPING = JVMTI_THREAD_STATE_ALIVE + // Thread.sleep()
JVMTI_THREAD_STATE_WAITING +
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +
JVMTI_THREAD_STATE_SLEEPING,
...
};