一、线程终止
可以看出来,当主线程访问这个结构时,结构体的内容已经被修改了。
linux下有两种方式可以使线程终止。第一种通过return从线程函数返回,第二种是通过调用函数pthread_exit()使线程退出。
#include
voidpthread_exit(void *retavl);
有两种特殊情况要注意:一种情况是,在主线程中,如果从main函数返回或者是调用exit函数退出主线程,则整个进程将终止,此时进程中的所有线程也将终止,因此在主线程中不能过早的从main函数返回;另一种情况如果主线程调用pthread_exit函数,则仅仅是主线程消亡,进程不回结束,进程内的其它线程也不会终止,直到所有线程结束,进程才会结束。
线程终止时的第一个问题:临界资源的释放。
临界资源为一个线程所独占,当一个线程终止时,如果不释放其占有的临界资源,则该资源会被认为还被已经退出的线程所使用,因此永远得不到释放。如果一个线程在等待使用这个临界资源,就可能无线的等待下去,这样就形成了死锁。所以linux系统提供了一对函数:pthread_cleanup_push()、pthread_cleanup_pop()用于自动释放资源。
线程终止时的另外一个问题:线程间的同步问题
一般情况下各个线程的运行是相互独立的,线程的终止并不会相互通知,也不会影响其它的线程,终止的线程占有的资源不回随着线程的终止而归还系统,而是仍为线程所有的进程持有。正如进程之间可以通过wait来等待,线程也有类似的函数:
#include
intpthread_join(pthread_t tid, void**ravl)如果执行成功则返回0,否则返回错误码。
该函数用来等待一个线程的结束。pthread_join的调用者将被挂起并等待tid线程终止。注意一个线程仅允许一个线程使用pthread_join函数来等待它的结束,并且被等待的线程可以出于join状态。一个可jion的线程所占的内存仅当有线程对其执行pthread_join函数后才释放,因此为了放置内存泄漏,所有的线程终止时都要设置为DETACHED,要么使用pthread_jion来回收资源。
下面是一个pthread_exit()的函数的无参类型指针是一个复杂的结构体地址,但是要注意这个结构体所使用的内存在调用者完成调用后必须仍然是有效的,否则就会出现无效或非法地址访问。如下面的例子
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct foo
{
int a, b, c, d;
};
void printfoo(const char *s, const struct foo *fp)
{
puts(s);
printf("structure at 0x%x\n", (unsigned)fp);
printf(" foo.a = %d\n", fp->a);
printf(" foo.b = %d\n", fp->b);
printf(" foo.c = %d\n", fp->c);
printf(" foo.d = %d\n", fp->d);
}
void *thr_fn1(void *arg)
{
struct foo foo = {1, 2, 3, 4};
printfoo("thread 1:\n", &foo);
pthread_exit((void *)&foo);
}
void *thr_fn2(void *arg)
{
printf("thread 2:ID is %u\n", pthread_self());
pthread_exit((void *)0);
}
int main(int argc, char *argv[])
{
int err;
pthread_t tid1, tid2;
struct foo *fp;
err = pthread_create(&tid1, NULL, thr_fn1, NULL);
err = pthread_join(tid1, (void *)&fp);
sleep(1);
printf("starting second thread!\n");
err = pthread_create(&tid2, NULL, thr_fn2, NULL);
sleep(1);
printfoo("parent:\n", fp);
return EXIT_SUCCESS;
}
结果为:
thread 1:
structure at 0xb7514350
foo.a = 1
foo.b = 2
foo.c = 3
foo.d = 4
starting second thread!
thread 2:ID is 3075558208
parent:
structure at 0xb7514350
foo.a = 0
foo.b = -1219409088
foo.c = -1219409088
foo.d = -1217671180