版权声明:本文为CSDN博主「summer_west_fish」的原创文章
原文链接:https://blog.csdn.net/summer_fish/article/details/108408572
文章目录
深入Java Thread底层实现
Thread start 源码揭秘
java.lang.Thread # start()
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
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 */
}
}
}
从上面的代码中,我们可以发现它会先去 判断 threadStatus
是不是 0, 不是的话会抛出异常 。
在 Thread 源码中我们可以发现 threadStatus
默认值就是 0
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0;
- 那什么时候会被改变呢?
- 这个 threadStatus 都有哪些值呢?
start0
状态的改变肯定伴随着线程的启动,所以我们直接来到下面这个 start0
方法
private native void start0();
Path:src/java.base/share/native/libjava/Thread.c
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},
};
jvm.cpp # JVM_StartThread()
Path: jdk\src\share\javavm\export\jvm.h
/*
* java.lang.Thread
*/
JNIEXPORT void JNICALL
JVM_StartThread(JNIEnv *env, jobject thread);
提示:这里 JNIEXPORT 和 JNICALL 都是 JNI 的关键字,表示此函数是要被 JNI 调用的
Path: hotspot/src/hotspot/share/prims/jvm.cpp
- 创建线程:
new JavaThread(&thread_entry, sz)
- 启动线程:
Thread::start(native_thread);
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_StartThread");
JavaThread *native_thread = NULL;
bool throw_illegal_thread_state = false;
// We must release the Threads_lock before we can post a jvmti event
// in Thread::start.
{
// 获取互斥锁
MutexLocker mu(Threads_lock);
// 线程状态检查,确保尚未启动
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
throw_illegal_thread_state = true;
} else {
jlong size =
java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
// 创建本地线程
NOT_LP64(if (size > SIZE_MAX) size = SIZE_MAX;)
size_t sz = size > 0 ? (size_t) size : 0;
// ===============================================================
// 创建C++级别的本地线程,&thread_entry为线程run方法执行入口
// ===============================================================
native_thread = new JavaThread(&thread_entry, sz);
// 检查该本地线程中是否包含OSThread,因为可能出现由于内存不足导致OSThread未创建成功的情况
if (native_thread->osthread() != NULL) {
// Note: the current thread is not being used within "prepare".
// ===============================================================
// 准备Java本地线程,链接Java线程 <-> C++线程
// ===============================================================
native_thread->prepare(jthread);
}
}
}
// ===============================================================
// 启动Java本地线程
// ===============================================================
Thread::start(native_thread);
JVM_END
**提示:**这里 JVM_ENTRY 和 JVM_END是两个宏定义,定义了函数体的头和尾。
创建线程
thread.cpp # JavaThread::JavaThread()
native_thread = new JavaThread(&thread_entry, sz);
线程构造器
Path: src/hotspot/share/runtime/thread.cpp
// C++级别Java线程构造方法
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
Thread()
#if INCLUDE_ALL_GCS
, _satb_mark_queue(&_satb_mark_queue_set),
_dirty_card_queue(&_dirty_card_queue_set)
#endif // INCLUDE_ALL_GCS
{
// 初始化实例变量
initialize();
_jni_attach_state = _not_attaching_via_jni;
// =============================================
// 设置Java执行线程入口,最终会调用
// =============================================
set_entry_point(entry_point);
// 创建系统级本地线程
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(this, thr_type, stack_sz);
创建内核线程
Path:hotspot/src/hotspot/os/linux/os_linux.cpp
bool os::create_thread(Thread* thread, ThreadType thr_type,
size_t req_stack_size) {
// 创建操作系统线程
OSThread* osthread = new OSThread(NULL, NULL);
if (osthread == NULL) {
return false;
}
// 把osthread状态设置为已分配
osthread->set_state(ALLOCATED);
// 绑定至JavaThread
thread->set_osthread(osthread);
// 初始化线程数形
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ThreadState state;
{
pthread_t tid;
// ========================================================
// 调用系统库创建线程,thread_native_entry为本地Java线程执行入口
// ========================================================
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
if (ret != 0) {
// Need to clean up stuff we've allocated so far
thread->set_osthread(NULL);
delete osthread;
return false;
}
// Store pthread info into the OSThread
osthread->set_pthread_id(tid);
// Wait until child thread is either initialized or aborted
{
Monitor* sync_with_child = osthread->startThread_lock();
MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
while ((state = osthread->get_state()) == ALLOCATED) {
sync_with_child->wait(Mutex::_no_safepoint_check_flag);
}
}
}
return true;
}
终于看到有点眼熟的函数了~ 哈哈哈
// Linux系统函数 pthread_create()
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
os_linux.cpp # *thread_native_entry()
thread_native_entry为本地Java线程执行入口
// 线程执行入口
// Thread start routine for all newly created threads
static void *thread_native_entry(Thread *thread) {
// 初始化当前线程,把当前线程加入到TLS里
thread->initialize_thread_current();
OSThread* osthread = thread->osthread();
// 获取同步锁
Monitor* sync = osthread->startThread_lock();
osthread->set_thread_id(os::current_thread_id());
// handshaking with parent thread
{
MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
// notify parent thread
osthread->set_state(INITIALIZED);
sync->notify_all();
// 等待调用os::start_thread(),然后继续执行
while (osthread->get_state() == INITIALIZED) {
sync->wait(Mutex::_no_safepoint_check_flag);
}
}
// =======================================================
// 调用JavaThread的run方法以便触发执行java.lang.Thread.run()
// =======================================================
thread->run();
return 0;
}
启动线程
另一个重点 : 初始化工作完成之后当前线程wait,等待调用Thread::start(native_thread);
Thread::start(native_thread);
Path: hotspot\src\share\vm\runtime\thread.cpp
void Thread::start(Thread* thread) {
if (!DisableStartThread) {
if (thread->is_Java_thread()) {
// 设置线程状态为RUNNABLE
java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(), java_lang_Thread::RUNNABLE);
}
// 启动本地线程
os::start_thread(thread);
}
}
在启动该线程之前,将线程状态初始化为 RUNNABLE。
不能在线程启动后设置,因为我们不知道 正确的线程状态,它可能在 MONITOR_WAIT 或 在睡眠或其他状态。
启动内核线程
Path: src/hotspot/share/runtime/os.cpp
void os::start_thread(Thread* thread) {
// guard suspend/resume
MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
OSThread* osthread = thread->osthread();
// osthread状态设为运行中
osthread->set_state(RUNNABLE);
// 最终启动线程
pd_start_thread(thread);
}
os_linux.cpp # os::pd_start_thread()
最终启动线程,位于src/hotspot/os/linux/os_linux.cpp
,通知子线程JavaThread继续往下执行
void os::pd_start_thread(Thread* thread) {
OSThread * osthread = thread->osthread();
assert(osthread->get_state() != INITIALIZED, "just checking");
Monitor* sync_with_child = osthread->startThread_lock();
MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
// 通知子线程继续往下执行
sync_with_child->notify();
}
全局函数notify
bool Monitor::notify() {
assert (_owner == Thread::current(), "invariant") ;
assert (ILocked(), "invariant") ;
if (_WaitSet == NULL) return true ;
NotifyCount ++ ;
// Transfer one thread from the WaitSet to the EntryList or cxq.
// Currently we just unlink the head of the WaitSet and prepend to the cxq.
// And of course we could just unlink it and unpark it, too, but
// in that case it'd likely impale itself on the reentry.
Thread::muxAcquire (_WaitLock, "notify:WaitLock") ;
ParkEvent * nfy = _WaitSet ;
if (nfy != NULL) { // DCL idiom
_WaitSet = nfy->ListNext ;
assert (nfy->Notified == 0, "invariant") ;
// push nfy onto the cxq
for (;;) {
const intptr_t v = _LockWord.FullWord ;
assert ((v & 0xFF) == _LBIT, "invariant") ;
nfy->ListNext = (ParkEvent *)(v & ~_LBIT);
if (CASPTR (&_LockWord, v, UNS(nfy)|_LBIT) == v) break;
// interference - _LockWord changed -- just retry
}
// Note that setting Notified before pushing nfy onto the cxq is
// also legal and safe, but the safety properties are much more
// subtle, so for the sake of code stewardship ...
OrderAccess::fence() ;
nfy->Notified = 1;
}
Thread::muxRelease (_WaitLock) ;
if (nfy != NULL && (NativeMonitorFlags & 16)) {
// Experimental code ... light up the wakee in the hope that this thread (the owner)
// will drop the lock just about the time the wakee comes ONPROC.
nfy->unpark() ;
}
assert (ILocked(), "invariant") ;
return true ;
}
惊喜,居然在这个代码中看到这段注释,这里提到 WaitSet , EntryList,cxq
这是 隐式锁 [[Synchronized 内部的实现原理呀]] 或者 称它为 [[Monitor机制]]
- WaitSet: 是一个等待队列,存放进入等待状态的线程
- cxq: 是一个竞争队列,所有请求锁🔒的线程会先到这里
- EntryList: 存放 cxq 中有资格成为候选资源去竞争锁的线程
运行线程
thread.cpp # JavaThread::run()
这里调用JavaThread的run方法以便执行java.lang.Thread.run()
用户逻辑代码,位于src/hotspot/share/runtime/thread.cpp
void JavaThread::run() {
// 执行run方法前的初始化和缓存工作
this->initialize_tlab();
...
// 通知JVMTI
if (JvmtiExport::should_post_thread_life()) {
JvmtiExport::post_thread_start(this);
}
EventThreadStart event;
if (event.should_commit()) {
event.set_thread(THREAD_TRACE_ID(this));
event.commit();
}
// ==================================================
// 执行Java级别Thread类run()方法内容
// ==================================================
thread_main_inner();
}
void JavaThread::thread_main_inner() {
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);
// ==========================================
// 执行线程入口java.lang.Thread # run()方法
// ==========================================
this->entry_point()(this, this);
}
DTRACE_THREAD_PROBE(stop, this);
// 退出并释放空间
this->exit(false);
// 释放资源
delete this;
}
jvm.cpp # thread_entry()
最终执行实例化JavaThread时设置的入口方法entry_point,代表了Java代码级别Java线程执行入口, 这里通过JavaCalls组件调用java.lang.Thread.run()
方法,执行真正的用户逻辑代码。
static void thread_entry(JavaThread* thread, TRAPS) {
HandleMark hm(THREAD);
Handle obj(THREAD, thread->threadObj());
JavaValue result(T_VOID);
// 执行Java调用
JavaCalls::call_virtual(&result,
obj,
SystemDictionary::Thread_klass(),
vmSymbols::run_method_name(),
vmSymbols::void_method_signature(),
THREAD);
}
线程状态
threadStatus 都有哪些值呢?
/*
* Java thread state support
*/
enum {
JAVA_THREAD_STATE_NEW = 0,
JAVA_THREAD_STATE_RUNNABLE = 1,
JAVA_THREAD_STATE_BLOCKED = 2,
JAVA_THREAD_STATE_WAITING = 3,
JAVA_THREAD_STATE_TIMED_WAITING = 4,
JAVA_THREAD_STATE_TERMINATED = 5,
JAVA_THREAD_STATE_COUNT = 6
};
惊喜,居然在这个代码中看到这段注释,这里提到 WaitSet , EntryList,cxq
这是 隐式锁 [[Synchronized 内部的实现原理呀]] 或者 称它为 [[Monitor机制]]
WaitSet: 是一个等待队列,存放进入等待状态的线程
cxq: 是一个竞争队列,所有请求锁🔒的线程会先到这里
EntryList: 存放 cxq 中有资格成为候选资源去竞争锁的线程