首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

线程有关问题的核心: 如何退出线程才是合适的-小话多线程(2)

2012-08-24 
线程问题的核心: 怎么退出线程才是合适的----小话多线程(2)作者:陈曦 日期:2012-8-516:13:36环境:[Mac 10.

线程问题的核心: 怎么退出线程才是合适的----小话多线程(2)

作者:陈曦

日期:2012-8-5  16:13:36

环境:[Mac 10.7.1 Lion Intel i3 支持64位指令 gcc4.2.1 xcode4.2 苹果开源代码Libc-763.11] 

转载请注明出处

每日总结:优秀的架构都是类似的,垃圾的架构一般都是一个原因:代码内部原理掌握得不够



Q1: main函数中最后用return 0; 和使用 exit(0); 退出进程到底有什么不同?

A: 一种很简单的区别方式就是return 0是返回给调用函数者,而exit(0)是直接返回给系统。但是,前者返回给什么函数?写如下代码:

线程有关问题的核心: 如何退出线程才是合适的-小话多线程(2)

首先要确定,程序的入口点默认是_start. 同时可以看到,main中最后只是简单的返回给调用者;但是start中首先调用了main,然后调用了exit,这说明了虽然main函数最后没做什么退出进程的事情,返回到start后依然会退出进程。

再看第二个:

线程有关问题的核心: 如何退出线程才是合适的-小话多线程(2)

线程有关问题的核心: 如何退出线程才是合适的-小话多线程(2)

可以看到,main最后调用了exit函数,start最后依然也调用了exit,但是start最后调用的exit已经无法运行到,因为main调用后进程就结束了。


由上面两种情况可以看出,main函数最后调用return 0; 或者 exit(0); 可以说是基本一样,除了程序流程有点变化,没有什么大的区别。



Q2: 主线程最后调用pthread_exit来退出可行吗?

A: 如果仅仅从退出主线程的角度来考虑,这是可行的; 但是,一般来说,进程应该总是主线程最后退出,这样比较符合编程的基本原则;如果这样的话,主线程使用pthread_exit退出就可能出问题: 因为,它虽然会释放已经注册的清理函数以及线程特有的数据,但是它并不一定会释放进程相关的资源(包括内存、信号量、互斥体等)或者执行进程注册的退出函数(如atexit注册的退出函数),这样就很有可能导致内存泄露。当然,上面说并不一定,是因为,如果主线程是进程中最后退出的线程,那么进程相关的资源和进程注册的退出函数才会被执行。为了明白pthread_exit内部调用关系,首先,我们下载苹果开源代码Libc-763.11,这是对应mac系统10.7.1的开源libc代码,如果是其它系统,请下载对应版本的代码。苹果开源代码网站: http://opensource.apple.com/

首先找到pthread_exit的实现代码:

typedef struct _pthread{long       sig;      /* Unique signature for this structure */struct __darwin_pthread_handler_rec *__cleanup_stack;pthread_lock_t lock;      /* Used for internal mutex on structure */uint32_tdetached:8,inherit:8,policy:8,freeStackOnExit:1,newstyle:1,kernalloc:1,schedset:1,wqthread:1,wqkillset:1,pad:2;size_t       guardsize;/* size in bytes to guard stack overflow */#if  !defined(__LP64__)int       pad0;/* for backwards compatibility */#endifstruct sched_param param;uint32_tcancel_error;#if defined(__LP64__)uint32_tcancel_pad;/* pad value for alignment */#endifstruct _pthread *joiner;#if !defined(__LP64__)intpad1;/* for backwards compatibility */#endifvoid           *exit_value;semaphore_t    death;/* pthread_join() uses this to wait for death's call */mach_port_t    kernel_thread; /* kernel thread this thread is bound to */void       *(*fun)(void*);/* Thread start routine */        void       *arg;      /* Argment for thread start routine */int       cancel_state;  /* Whether thread can be cancelled */int       err_no;/* thread-local errno */void       *tsd[_EXTERNAL_POSIX_THREAD_KEYS_MAX + _INTERNAL_POSIX_THREAD_KEYS_MAX];  /* Thread specific data */        void           *stackaddr;     /* Base of the stack (is aligned on vm_page_size boundary */        size_t         stacksize;      /* Size of the stack (is a multiple of vm_page_size and >= PTHREAD_STACK_MIN) */mach_port_t    reply_port;     /* Cached MiG reply port */#if defined(__LP64__)        intpad2;/* for natural alignment */#endifvoid           *cthread_self;  /* cthread_self() if somebody calls cthread_set_self() *//* protected by list lock */uint32_t childrun:1,parentcheck:1,childexit:1,pad3:29;#if defined(__LP64__)intpad4;/* for natural alignment */#endifTAILQ_ENTRY(_pthread) plist;void *freeaddr;size_tfreesize;mach_port_tjoiner_notify;charpthread_name[MAXTHREADNAMESIZE];/* including nulll the name */        intmax_tsd_key;void *cur_workq;void * cur_workitem;uint64_t thread_id;} *pthread_t;


总之,线程退出不是什么多么可怕的东西,操作系统大量用线程技术,上层的软件也不应该对此如此惧怕。

pthread_exit和pthread_cancel都是不错的选择; 不过,需要注意清理函数、资源释放的正确,以减少死锁问题的产生,减少线程意外崩溃问题的产生。



作者:陈曦

日期:2012-8-5  16:13:36

环境:[Mac 10.7.1 Lion Intel i3 支持64位指令 gcc4.2.1 xcode4.2 苹果开源代码Libc-763.11] 

转载请注明出处

每日总结:  优秀的架构都是类似的,垃圾的架构一般都是一个原因:代码内部原理掌握得不够



3楼IVERS0N5小时前
来学习了
2楼radxiaohe8小时前
谢谢分享,学习了
1楼haishiniwota前天 18:30
多线程刚接触,借鉴一下。

热点排行