免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2008 | 回复: 6
打印 上一主题 下一主题

[C++] 请教关于线程的基础问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-10-04 11:25 |只看该作者 |倒序浏览

.1线程可以从固定地址启动吗?
//在项目中遇到线程中有内存泄露,但是每次泄露地址不一样,如果线程能够固定地址,
估计会对抓住memory leak有很大帮助。


2. 主线程返回,子线程依旧执行,这种情形存在吗?
当前,我认为,存在,只有所有的线程退出,进程才消亡。
但是,我又想,主线程退出,会释放相应的资源,子线程如果访问主线程
申请的资源,那就不行了。
所以,就提出这个问题。


3.一个线程申请了动态内存,然后进入轮询。这种粗暴的设计会带来内存泄露,
怎么解决啦?

.我想,可以考虑线程通信.
进程一旦退出,在主线程的退出函数,发送一个信号(semaphore)给轮询的线程,
轮询线程收到后,就做对应的清理操作

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
2 [报告]
发表于 2012-10-04 11:47 |只看该作者
本帖最后由 linux_c_py_php 于 2012-10-04 12:02 编辑

1, valgrind 检测一下, 让同事帮你想想.
2, 主线程退出, 进程立即退出, 除非注册atexit.
  1. NAME
  2.        atexit - register a function to be called at normal process termination

  3. SYNOPSIS
  4.        #include <stdlib.h>

  5.        int atexit(void (*function)(void));

  6. DESCRIPTION
  7.        The  atexit()  function  registers the given function to be called at normal process termination, either via exit(3) or via return from the pro-
  8.        gram’s main().  Functions so registered are called in the reverse order of their registration; no arguments are passed.
复制代码
3, 维护一个线程列表:
  1. typedef enum {
  2.       WORKING, //在工作
  3.       EXITING,   //已通知退出, 但尚未退出, 由主线程设置
  4.       EXITED     //线程已退出, 可以pthread_join回收, 由子线程设置
  5. }thread_status_t;

  6. typedef struct thread_st {
  7.       pthread_t tid;
  8.       int dead_pipe[2];
  9.       thread_status_t status;
  10. }*thread_t;

  11. typedef struct thread_list_st {
  12.       int n_total;
  13.       int n_used;
  14.       pthread_mutex_t mutex;
  15.       thread_t *list;
  16. }*thread_list_t;

复制代码
轮询线程里放个select/unblocked read + pipe, 也可以lock+check+unlock(不建议).

比如, 主线程想让 thread_list_t->list[0] 退出,  就lock thread_list_t->mutex, 设置thread_list_t->list[0]->status = EXITING(先确定status==WORKING), 然后Unlock mutex, 最后向thread_list_t->list[0]->dead_pipe[1]写1字节通知线程退出.

轮询线程在轮询过程中select到thread_list_t->list[0]->dead_pipe[0]可读, read 1个字节成功, 之后准备准备退出工作, 该放的内存赶紧放, 之后lock mutex, 设置thread_list_t->list[0]->status = EXITED, 然后Unlock, 就可以pthread_exit/return退出了.

主线程里一样是轮询结构, 每次轮询Lock后扫列表找一个exited的线程, 调用pthread_join回收即可.


论坛徽章:
0
3 [报告]
发表于 2012-10-04 12:00 |只看该作者
linux_c_py_php 发表于 2012-10-04 11:47
1, valgrind 检测一下, 让同事帮你想想.
2, 主线程退出, 进程立即退出, 除非注册atexit.3, 维护一个线程列 ...


这么快,就有回音。
我好好读读

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
4 [报告]
发表于 2012-10-04 12:00 |只看该作者
上边的方法是apache的MPM里使用的一种技巧, 一方面可以精确到单个线程的控制, 一方面保证主线程不会因为pthread_join阻塞, 另外线程直接detach的话可以避免join(实际上这一步多了不多, 少了不少, 与线程控制没多少关系).

如果是要杀整个线程池的需求, 一个全局原子变量就足够了, volatile sig_atomic_t should_exit;  每个轮询线程在轮询时直接去检查就行了, 主线程想关线程池就设置一下OK, 完全没必要kill信号来设置这个should_exit, 用信号要么是用户通过shell环境进行进程控制, 要么是master-worker架构的程序, 可以支持master kill worker some signal的方法来实现进程控制(master-worker间同样可以做pipe/socketpair做控制).

一个好程序是必须做线程管理和进程管理的, 不能说暴力的让进程退出就得了, 线程自生自灭去吧, 那太糟烂了, 而且没法做到运行中的动态线程/进程管理与规模调整, 你强退进程还可能退出时弄出个大core, 太业余了.

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
5 [报告]
发表于 2012-10-04 12:14 |只看该作者
本帖最后由 linux_c_py_php 于 2012-10-04 12:28 编辑
linux_c_py_php 发表于 2012-10-04 12:00
上边的方法是apache的MPM里使用的一种技巧, 一方面可以精确到单个线程的控制, 一方面保证主线程不会因为pth ...


像apache的MPM, 主线程做线程管理, listen线程做监听accept, worker线程负责连接处理, listen与worker间通过mutex+cond+queue交互, listen线程在queue满时挂起在cond, 直到被worker唤醒才继续accept, 以此达到控制连接数的目的.

我的意思就是, 怎么解决问题是根据问题自身来设计的, 没有通用的方法. 这里listen完全可能挂起在cond上, 这时候你怎么让一个挂起的线程退出? 只能让listen在挂起cond之前的检测中去检查一个变量, 我们想让listen退出的话只需要设置变量, 然后cond_signal唤醒listen让它去检查到这个变量, 才会让listen意识到退出, 其他办法似乎都没法解决, 因为程序就是这样的, 必须根据实际情况给出解决方案.

apache的worker进程退出又分暴力退出和优雅退出, 但这和楼主所说的暴力是两码事.

暴力退出是说listen和worker线程同时通知退出, 并且worker线程不完成当前的请求就从中途立即退出, 这一方面通过一个mutex保护的变量+cond_signal来通知整个worker线程池(防止有些此时已经挂起的), 另外需要设置一个全局原子变量, 每个worker线程在多个函数的失败返回点, 比如read等(errno == EINTR), 或者其他普通点铺设几个检测点, 一旦检测到原子量就立即清理连接并退出线程. listen线程一样, 我们依旧通过一个mutex保护的变量设置, 配置cond_signal唤醒, 之后listen线程也就退出了.

优雅退出是说只通知listen退出, 即先让listen停止接受新的连接, 之后由Listen向worker线程池通知退出, worker线程必须循环至queue中没有连接才会退出, 这样就避免了暴力退出给用户带来的不响应现象.

论坛徽章:
0
6 [报告]
发表于 2012-10-04 14:06 |只看该作者
linux_c_py_php 发表于 2012-10-04 12:00
一个好程序是必须做线程管理和进程管理的, 不能说暴力的让进程退出就得了, 线程自生自灭去吧, 那太糟烂了, 而且没法做到运行中的动态线程/进程管理与规模调整, 你强退进程还可能退出时弄出个大core, 太业余了

嗯,管理进程退出是个 大学问。从以前只是完成功能,到让功能稳定的运行,这是一个过程。学习中

论坛徽章:
0
7 [报告]
发表于 2012-10-04 14:07 |只看该作者
linux_c_py_php 发表于 2012-10-04 12:14
像apache的MPM, 主线程做线程管理, listen线程做监听accept, worker线程负责连接处理, listen与worker间 ...

当初我写暴力退出,也是没法的事。
所以每当看以前代码的时候,总觉得臭臭的。 向好代码看齐。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP