多线程_01_执行原理
public class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("当前线程执行的代码");
}
public static void main(String[] args) {
new ThreadDemo().start();
}
}
此处思考,该线程背后的执行原理。
1.从JAVA层面看start()执行
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
主要调用start0()
private native void start0();
2. JAVA native 和 Hostpot映射关系 由于是native 这里转至JVM层面 这里有个技巧,关于JAVA native 和 Hostpot映射关系 http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/00cd9dc3c2b5/src/share/native/java/lang/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},
};
3. 追踪JVM_StartThread
根据映射 追踪JVM_StartThread
方法,进入jvm.cpp
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_StartThread");
JavaThread *native_thread = NULL;
...
native_thread = new JavaThread(&thread_entry, sz);
if (native_thread->osthread() != NULL) {
// Note: the current thread is not being used within "prepare".
native_thread->prepare(jthread);
}
}
}
...
Thread::start(native_thread);
解析:
这里着重调用两个方法,①是构造方法new JavaThread(&thread_entry, sz)
,②是Thread::start(native_thread)
,
4. 追踪构造方法new JavaThread(&thread_entry, sz)的参数thread_entry 仍然是jvm.cpp中
static void thread_entry(JavaThread* thread, TRAPS) {
HandleMark hm(THREAD);
Handle obj(THREAD, thread->threadObj());
JavaValue result(T_VOID);
JavaCalls::call_virtual(&result,
obj,
KlassHandle(THREAD, SystemDictionary::Thread_klass()),
vmSymbols::run_method_name(),
vmSymbols::void_method_signature(),
THREAD);
}
解析: 我们需要注意call_virtual方法中的几个参数:
obj:
就是当前线程对象
vmClasses::Thread_klass():
表示调用的对象的类型是java.lang.Thread
vmSymbols::run_method_name():
表示调用的方法是 run
vmSymbols::void_method_signature():
表示返回结果是空。
映射关系如下:
vmClassMacros.hpp 中
do_klass(Thread_klass,java_lang_Thread)
vmSymbols.hpp 中
template(run_method_name, "run")
5. 追踪追踪构造方法new JavaThread(&thread_entry, sz) 仍然是jvm.cpp中
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
Thread()
...
initialize();
_jni_attach_state = _not_attaching_via_jni;
set_entry_point(entry_point);
os::ThreadType thr_type = os::java_thread;
os::create_thread(this, thr_type, stack_sz);
...
}
解析: 这里关注两个方法 ①调用set_entry_point 就向线程中注册了回调函数;②create_thread 方法在os.hpp文件中
static bool create_thread(Thread* thread, ThreadType thr_type, size_t stack_size = 0);
6. 追踪create_thread 由于Java跨平台性,这里默认展示linux,即os_linux.cpp文件
bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
...
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
...
}
解析:
这里调用了java_start
方法
7. 追踪java_start方法 仍然在os_linux.cpp文件中
static void *java_start(Thread *thread) {
ThreadLocalStorage::set_thread(thread);
OSThread* osthread = thread->osthread();
Monitor* sync = osthread->startThread_lock();
if (!_thread_safety_check(thread)) {
// notify parent thread
MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
osthread->set_state(ZOMBIE);
sync->notify_all();
return NULL;
}
...
{
MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
// notify parent thread
osthread->set_state(INITIALIZED);
sync->notify_all();
// wait until os::start_thread()
while (osthread->get_state() == INITIALIZED) {
sync->wait(Mutex::_no_safepoint_check_flag);
}
}
// call one more level start routine
thread->run();
return 0;
}
解析:
可以看出将当前当前线程wait,当调用了start_thread()方法的时候。就会唤醒(notify_all()),然后就是回调run(),也就是回调我们刚才向线程中注册的方法。既而指明run方法执行方式是回调执行的。
通过注释表示线程创建后是wait了,在os::start_thread()
时notify了。
8. 追踪run()
跟着run() 追踪到thread.cpp,内部执行一个thread_main_inner()
// The first routine called by a new Java thread
void JavaThread::run() {
...
...
// We call another function to do the rest so we are sure that the stack addresses used
// from there will be lower than the stack base just computed
thread_main_inner();
}
9. 追踪thread_main_inner() 依旧在thread.cpp文件中
void JavaThread::thread_main_inner() {
assert(JavaThread::current() == this, "sanity check");
assert(this->threadObj() != NULL, "just checking");
// Execute thread entry point unless this thread has a pending exception
// or has been stopped before starting.
// Note: Due to JVM_StopThread we can have pending exceptions already!
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);
this->entry_point()(this, this);
}
DTRACE_THREAD_PROBE(stop, this);
this->exit(false);
delete this;
}
解析:
在这里看到一个熟悉的方法entry_point()
就是上面
set_entry_point注册回调方法,既而表示run()执行方法是回调执行。
这里有一个疑惑点,就是在第7步解析中看到注释表明线程创建后是wait,在执行os::start_thread()后是notify的。接下里我们就确认这个os::start_thread()后是不是notify了?
10.追踪Thread::start(native_thread)
这里是上述3步骤提到的②Thread::start(native_thread)
方法逻辑
void Thread::start(Thread* thread) {
trace("start", thread);
if (!DisableStartThread) {
if (thread->is_Java_thread()) { java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
java_lang_Thread::RUNNABLE);
}
os::start_thread(thread);
}
}
11.追踪os::start_thread(thread) 追踪到os_linux.cpp文件中
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();
}
解析: 这里的最后一行代码已经确认了我们上面提到的疑惑,至此,小伙伴们明白了吗?欢迎大家在评论区留言指正,谢谢。
总结流程图
- 感谢你赐予我前进的力量