目录
频道首页
join唤醒线程原理与c++析构函数有关
收藏
0
Rocky-BCRJ 最近修改于 2023-04-25 11:09:35

@[toc]

在使用 join 方法, 它到底是如何去唤醒线程的呢, 希望这篇文章可以帮助到你解决问题

析构函数简介

析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。

c++的退出线程方法

void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
    // 省略代码
      ensure_join(this); // ensure_join是线程退出时调用(内部会调用notifyAll)
   // 省略代码       
}

thread.cpp#ensure_join

static void ensure_join(JavaThread* thread) {
  Handle threadObj(thread, thread->threadObj());
  assert(threadObj.not_null(), "java thread object must exist");
  ObjectLocker lock(threadObj, thread); // 创建ObjectLocker(构造函数加锁,析构函数解锁)
  thread->clear_pending_exception();  // 清除待处理异常,因为线程准备退出了
  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED); // 设置线程状态为 TERMINATED
  java_lang_Thread::set_thread(threadObj(), NULL);// 将属性设置为null, 这样 is_alive方法就会返回 false
  lock.notify_all(thread); // 唤醒所有关联的重量级锁上等待的线程
  thread->clear_pending_exception(); // 清除待处理异常(走到这个地方 ObjectLocker生命周期结束,自动调用析构函数)
}

synchronizer.cpp

在学习 线程通信的时候发现 synchronizer.cpp 这段代码挺有意思的。小伙伴们在学习 wait/notify/notifyAll 肯定会遇到的,故这里演示一下。

ObjectLocker::ObjectLocker(Handle obj, Thread* thread, bool doLock) {
  _dolock = doLock;
  _thread = thread;
  debug_only(if (StrictSafepointChecks) _thread->check_for_valid_safepoint_state(false);)
  _obj = obj;

  if (_dolock) {
    TEVENT (ObjectLocker) ;

    ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread);// 构造函数加锁
  }
}

ObjectLocker::~ObjectLocker() { // 析构函数(一般用来和构造函数执行相反的动作)
  if (_dolock) {
    ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread);
  }
}

测试析构函数代码

#include <iostream>

using namespace std;

class Test{
public:
    void setLength(double length);
    double getLength(void);
    Test();
    ~Test();

private:
    double length;
};
Test::Test(void) {
    cout << "=======begin=======";
}
Test::~Test(void) {
    cout << "=======end=========";
}
void Test::setLength(double length) {
    length = length;
}
double Test::getLength(void) {
    return length;
}

int main() {
    Test test;

    test.setLength(6.0);
    cout << "length: " << test.getLength() << endl;
    return 0;
}

`执行如下指令

g++ -o Test Test.cpp
./Test

输出结果

=======begin=======
length: 2.0736e-317
=======end=========

文末总结

以前还不懂为啥用个 join 就能阻塞线程, 然后其他线程跑完 main 线程才会继续走后面的流程, 原来是因为在其他线程退出的时候去调用了析构函数啊。

内容大纲
批注笔记
join唤醒线程原理与c++析构函数有关
ArticleBot
z
z
z
z
主页
Git管理
文章
云文档
留言墙
AI文档