Zade's Weblog

程序人生

Category Archives: parallel

线程同步和日志

当主线程退出的时候,一般的逻辑是要所有的子线程join,这样以来不至于使得所有的子线程被强行的中断。
我现在的程序的逻辑是一旦主线程退出,我需要某种渠道告诉子线程,如果你处理完了所有的任务,那么你也退出吧。在所有的线程

退出以后,我还要通过日志记载资源释放的情况。
大体的代码架构如下:
main_thread()
{
run_when_recieve_term_signal;
send_term_tasks_to_all_sub_threads;
all_sub_threads_join;
}
sub_thread()
{
run_handle_tasks_when_receive_term_task;
exit_thread;
}
main_function()
{
//some other process
main_thread();
log_when_resources_are_released;
}
我现在遇到的问题是,一旦主程序退出,资源释放的日志并没有写入。问题在什么地方?
我简单的分析了一下,因为主线程向子线程发送结束任务的以后,然后再让所有的子线程join,但是这个时候可能子线程已经收到结

束任务的命令,并且已经退出,在这个卡当,会不会产生微妙的问题?因为资源释放的日志都是在主线程发出的。
所以我的策略是让子线程join以前,主线程休眠一段时间:
main_thread()
{
run_when_recieve_term_signal;
send_term_tasks_to_all_sub_threads;
sleep;
all_sub_threads_join;
}
我的理解不知道对不对,因为我也找不到相关的知识,但是结果如我所愿了。

异步调用的模式

今天读了sutter的文章 Prefer Futures to Baked-In “Async APIs”, 下面是一些体会.

多线程编程是复杂的,保证正确的使用多线程,应该在使用模式上寻找突破.也就是说,我们应该枚举一些经过实践证明的,易用的异步调用模式.

以前我就有一些这样的感觉,不过总是模糊的,经验性的.sutter一直在做这方面的工作,他在这篇文章中对比了微软现在使用的BeginXXX/EndXXX的模式和新型的Future模式.

BeginXXX/EndXXX模式的主要缺点:

  1. 对API设计者而言,这是侵入式的方法,破坏了原来API的简洁性. 一个API分成3个,复杂性随之而来
  2. 对API的使用者而言,必须要按照固定的次序调用,Begin,Wait,End;否则,轻者资源泄漏,重者程序崩溃
  3. 增加形式上的复杂性.因为有的用户并不需要等待,只要执行完毕即可
  4. 这种方法没有给予用户机会如何进行异步调用,比如是否使用线程池等

当然,使用Future模式就好多了,在和lambda结合以后,在形式上会更加的简洁.

看完以后,我的疑问是,微软为什么留着Future不同,而提供了BeginXXX/EndXXX这种蹩脚的模式呢?继而哑然而笑,当然是因为微软当时还没有足够的技术积累使用Future模式了,下一个版本就要提供了,这当然是出于市场的需要.

Future模式的出现,表明在操作系统底层,编程语言设计层面的工作已经比较完善(我们不在需要复杂的直接用thread的了);在应用层面的工作就是按照所谓的数据流,任务流模式分解,然后使用这些工具(Future).

另外给我的提示是(和我原来的感觉一样):在API设计层面上不要过多的考虑多线程调用,就像早期的单线程API一样设计.在多线程环境下使用是调用者的事情.