深入Phtread(一):线程的一生
深入Phtread(一):线程的一生
我们每个人都并行地活在这个世界上 ,每一天每个人都干着不同的事情。每个人的人生都是不同的,从出生 -> 活着 -> 死去, 个中滋味,只能自己体味了。我们的线程兄弟也一样,只不过它的环境没有人类社会这么复杂,它的一生,被操作系统控制,被我们程序员控制着!呵呵,想想都觉得这兄弟可怜啊!不过这哥们可不许小瞧了,功能大了去了!具体线程的定义和好处参考其它关于线程的资料。该篇主要讲线程兄弟的大体的一生(从被创建到销毁)。进入正题:
线程的一生始终处于下面四种状态之一:
State | Meaning |
Ready | 就绪状态,等待处理器的调度。可能是刚新创建的,或阻塞状态,等待的资源得到满足刚解除阻塞状态,或处于运行状态被别的线程抢占了处理器。 |
Running | 运行状态,线程正在处理器上运行。多处理器可能会不止一个线程正在运行。 |
Blocked | 阻塞状态,线程等待某些资源,不能运行。如:等待一个条件变量,锁定互斥量,或者等待I/O操作的完成。 |
Terminated | 终止状态,线程从它的开始函数(创建时指定的)终止。调用pthread_exit或者被其它线程取消(cancelled)。此时,线程并没有被分离(detached),也没有被连接(joined)。一旦线程被joined或detached, 将会被系统回收。 |
线程的状态图:
1. 创建和使用线程常见的pthread函数
pthread_t thread;
int pthread_equal(pthread_t t1, pthread_t t2);
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start)(void*), void* arg);
pthread_t pthread_self();
int sched_yield();
int pthread_exit(void* value_ptr);
int pthread_detach(pthread_t thread);
int pthread_join(pthread_t thread, void** value_ptr);
2. 创建线程:
有一个比较特殊的线程, 就是主线程或者称为初始线程,它是当一个进程被创建时创建的。而其他线程则是在初始线程中调用pthread_create创建的。创建的新线程初始为Ready状态,等待处理器调度。
3. 执行线程:
线程被创建后,就会执行phtread_create的start参数指定的函数,我们可以通过pthread_create的arg参数向线程开始函数传递一个参数,若不想传就直接赋值NULL。
上面提到了一个特殊的线程:初始线程,它的开始函数就是我们学习C/C++见到的第一个函数main,只不过这个开始函数不是由我们来调用的,而是由操作系统Shell。操作系统先初始化进程,然后运行主线程的开始函数main。注意:初始线程和我们自己创建的线程有稍许不同:-开始函数参数不同,main的参数是int arg, char* argv,而我们自己的线程参数是void* arg。-自己创建的线程开始函数返回了,其它线程可以继续执行。而初始线程开始函数main返回后进程会终止,导致其它正在运行的线程也就被强行终止,若不想在main退出后关闭进程,可以在main最后调用pthread_exit,不过此时该进程就成了僵尸进程(defunct),直到所有线程执行完毕。- 还有一个很重要的区别,多数系统上,初始线程使用的是进程的栈,而自己创建的线程则使用自己的栈,往往自建线程的栈没有初始线程的栈空间大,要注意线程栈溢出哦!(phread提供了修改线程栈大小的函数,后面再说^_^)
4. 运行和阻塞
线程兄弟和我们一样,不能一直都醒着工作,它也要休息。线程一生大多处于三种状态:ready, running, 和blocked(和我一样,吃饭,工作,睡觉^_^)。 线程被创建时出于就绪状态,就绪状态等待处理器,处理器有空闲了,线程就转到运行状态疯狂工作,突然发现自己需要的其它资源(互斥量,条件变量)在别的线程手里,或者别的线程优先级比自己大一下从它手里抢走了处理器,或处理器烦了它了(时间片已经用完),或自己不好意思不干事还占用处理器了(等待I/O操作完成),就转换成阻塞状态,停止运行,可以休息下了。 休息可不是给它放长假,任务还没完成了...继续,当等待的资源得到满足,再次投入工作,进入运行状态。周而复始,直到任务完成。
5. 终止线程:
线程一般都是在开始函数执行完时终止的。线程开始函数中调用pthread_exit或者其它线程调用pthread_cancel都可以终止线程。终止后线程处于terminated状态(注意:不是destroyed),然后等待系统回收。
若创建线程时指定线程是detached的,直接在线程开始函数执行完后就会被回收。
若是joinable,那就需要初始线程或其他线程调用pthread_join来等待要终止的线程了, 同时还可以通过pthread_joind的第二个参数获得线程的返回值。pthread_join后,线程就被detached,然后被系统回收。
6. 回收线程
线程创建时,detachsate属性是PTHREAD_CREATE_DETACHED,则在开始函数返回后被回收。
或其他线程使用了pthread_join 或自己调用了pthread_detach,线程出于terminated状态后,立马就会被系统回收:释放系统资源和进程资源,包含线程返回值占用的内存,线程堆栈,寄存器状态等等。
今天就到此,以后深挖!^_^
author:david(heaven.hell.or@gmail.com)