`

关于子线程释放的时机

 
阅读更多
void test() {
	ThreadRunner mThread("test");
	int mCount = 1;
	mThread.start([&mCount] {
		mCount++;
		printf("thread run...%d\n", mCount);
		std::chrono::milliseconds sleepDuration(2000);
		std::this_thread::sleep_for(sleepDuration);
		return true;
	});
	cout << "test end..\n" << endl;
}

int main()
{
	test();
	cout << "test out..\n" << endl;
}
ThreadRunner created. name:test
ThreadRunner created. name:test
test end..
ThreadRunner started. name:test
thread run...2

thread run...3
thread run...4
thread run...5
thread run...6
thread run...7
thread run...8
thread run...9
thread run...10
thread run...11
thread run...12
thread run...13
thread run...14
thread run...15
thread run...16

     由于test()函数退出时会对ThreadRunner进行析构,而子线程循环运行,永远无法析构,导致main()函数无法执行到下一步。也就是说,虽然启动了子线程,但main()要等待子线程执行完毕。函数局部变量子线程会引起函数阻塞无法退出。

static ThreadRunner mThread("test");

void test() {
	int mCount = 1;
	mThread.start([&mCount] {
		mCount++;
		printf("thread run...%d\n", mCount);
		std::chrono::milliseconds sleepDuration(2000);
		std::this_thread::sleep_for(sleepDuration);
		return true;
	});
	cout << "test end..\n" << endl;
}

int main()
{
	test();
	cout << "test out..\n" << endl;
}
ThreadRunner created. name:test
test end..
ThreadRunner started. name:test

thread run...2
test out..

请按任意键继续. . . thread run...1946155304
thread run...1946155305
thread run...1946155306
thread run...1946155307
thread run...1946155308
thread run...1946155309
thread run...1946155310
thread run...1946155311
thread run...1946155312

    由于ThreadRunner是全局的,函数test() 退出时并不会引起ThreadRunner析构,所以也不会阻塞main()运行。但是mCount局部变量已经释放,所以子线程中的mCount引用的值是随机数。不要传递局部变量的引用给子线程。

 

static ThreadRunner *mThread = nullptr;

void test(const int mCount) {
	if (mThread == nullptr) {
		mThread = new ThreadRunner("test");
	}
	if (mThread->isRunning()) {
		delete mThread; // 会阻塞等待前一个线程析构,如果不delete,则前一个线程成为野指针
		mThread = new ThreadRunner("test2");
	}
	mThread->start([mCount] {
		printf("thread run...%d\n", mCount);
		std::chrono::milliseconds sleepDuration(2000);
		std::this_thread::sleep_for(sleepDuration);
		printf("thread run.end..%d\n", mCount);
		return false;
	});
	cout << "test end..\n" << endl;
}

int main()
{
	test(1);
	cout << "test out..\n" << endl;
	test(2);
	cout << "test out.2.\n" << endl;
}

 

分享到:
评论

相关推荐

    线程的同步 操作系统

    - 子线程释放信号量后,主线程继续执行,处理后续逻辑。 #### 运行结果与实验心得 通过运行实验程序,我们可以观察到子线程先于主线程执行,且在子线程执行完毕后,主线程被唤醒并继续执行。这一过程完美体现了...

    控制多个线程结束,后再执行统计结果

    这篇博客“控制多个线程结束,后再执行统计结果”很可能探讨了如何在多线程环境中,等待所有子线程执行完毕后,再执行最后的统计操作。 线程同步的主要目的是防止数据竞争和死锁,确保共享资源的安全访问。Java提供...

    线程调用进程设计文档1

    在主线程中创建子线程,子线程调用`fork()`,并在子进程中执行`execl()`。主线程接收信号并处理超时情况,确保进程不会无限制地运行。 - 方案二:使用线程池和任务队列。创建一个线程池,线程池中的线程负责处理...

    android面试题

    了解这些方法的调用时机以及如何合理利用它们来管理资源(如关闭耗电的操作、释放内存等)是非常重要的。 #### 2. 进程与服务的优先级及杀进程策略 Android系统为了保证用户体验,会对进程进行优先级划分,并根据...

    Android开发工程师面试题之handler详解。android程序员,android开发面试资料,详解

    - **作用**:主要用于子线程与主线程之间的通信,通过发送消息的方式改变UI界面状态或执行特定的任务。 - **实现机制**:基于消息队列(Message Queue)和循环器(Looper)来实现。 2. **核心组件介绍**: - **...

    android 开发技巧

    - 学习并理解`Handler`、`Looper`和`Message`的工作原理,用于主线程和子线程间的消息传递。 - 使用`RxJava`或`LiveData`进行响应式编程,简化异步操作处理。 - 利用`WorkManager`来管理后台任务,确保其在合适的...

    Android常见原理性面试专题.docx

    - HandlerThread:预封装了Looper的线程,启动后自动运行Looper,方便在子线程中处理消息。调用quit()或quitSafely()方法可安全退出HandlerThread的循环。 3. **ThreadLocal原理** ThreadLocal是线程局部变量,它...

    联想Android面试题

    - 通过子线程发送消息到主线程的消息队列中,主线程中的Looper不断从消息队列中取出消息,并通过Handler分发到对应的处理方法。 #### 5. Activity、Intent、Service的关系 - **Activity**是用户界面的基本组成部分...

    高级Java经典面试题2019

    `InheritableThreadLocal`允许子线程继承父线程中的变量值。它的实现基于`Thread`类中的`copyStateFrom`方法,将父线程的`ThreadLocal`值复制到子线程。 #### CyclicBarrier与CountDownLatch的不同 - **...

Global site tag (gtag.js) - Google Analytics