当前位置:早雪网网络学院编程文档C/C++ → Solaris2.4 多线程编程指南2--用多线程编程

Solaris2.4 多线程编程指南2--用多线程编程

减小字体 增大字体 作者:不详  来源:supcode.com收集整理  发布时间:2005-7-22 19:39:44
回值--当调用线程是进程中的最后一个非守护线程,进程将用状态0退出。 当最初的线程从main()函数中返回时进程用该线程main函数的返回值退出。
线程可以通过两种方式停止执行。第一种是从最初的过程中返回。第二种是 提供一个退出代码,通过调用thr_exit()结束。下面的事情依赖于在线程创建时 flags的设置。
线程A终止的缺省操作(当flags的相应位设为0时,执行缺省操作)是保持 状态,直到其它线程(不妨设为B)通过"联合"的方式得知线程A已经死亡。联合 的结果是B线程得到线程A的退出码,A自动消亡。你可以通过位或来给flags的 THR_DETACHED参数置位,使得线程在thr_exit()之后或从最初过程返回后立即消 亡。在这种情况下,它的退出码不会被任何线程获得。
有一个重要的特殊情况,在主线程--即最初存在的线程--从主函数返回或调 用了exit(),整个进程将终止。所以在主线程中要注意不要过早地从主函数main 返回。
如果主线程仅仅调用了thr_exit(),仅仅是它自己死亡,进程不会结束,进 程内的其他线程将继续运行(当然,如果所有的线程都结束,进程也就结束了)。
如果一个线程是非分离的,在它结束后一定要有其它进程与它"联合",否则 该线程的资源就不会被回收而被新线程使用。所以如果你不希望一个线程被 "联合",最好按照分离线程来创建。
另外一个flag参数是THR_DAEMON。使用这个标志创建的线程是守护线程,在 其他线程终止之后,这些线程自动终止。这些守护线程在线程库内部特别有用。 守护线程可以用库内函数创建--在程序的其他部分是不可见的。当程序中所 有的其他线程终止,这些线程自动终止。如果它们不是守护线程,在其它线程终 止后他们不会自动终止,进程不会自动结束。

2.1.8等待线程结束

thr_join(3T) 用thr_join函数来等待线程终止。
#include
int thr_join(thread_t wait_for,thread_t *departed,void **status);
thr_join()函数阻塞自身所在的线程,直到由wait_for指定的线程终止。指 定的线程一定与本线程在同一个进程内部,而且一定不是分离线程。当wait_for 参数为0时,thr_join等待任何一个非分离线程结束。换句话说,当不指定线程 号时,任何非分离线程的退出将导致thr_join()返回。
当departed参数不是NULL时,在thr_join正常返回时它指向存放终止线程ID 的地址。当status参数不是NULL时,在thr_join正常返回时它指向存放终止线程 退出码的地址。
如果线程创建时指定了堆栈,在thr_join返回时堆栈可以被回收。由它返回 的线程号可以被重新分配。
不能有两个线程同时等待同一个线程,如果出现这种情况,其中一个线程正 常返回,另外一个返回ESRCH错误。
返回值--thr_join()在正常执行后返回0,其他值意味着错误。在以下情况 发生时,函数失败并返回相关值。
ESRCH wait_for不合法,等待的线程为分离现成。
EDEADLK 等待自身结束。
最后步骤
thr_join()有三个参数,提供了一定的灵活性。当你需要一个线程等待 直到另外一个指定的线程结束,应当把后者的ID提供为第一参数。如果 需要等待到任何其他的线程结束,将第一参数置零。
如果调用者想知道是那个线程终止,第二参数应当是储存死线程的ID的地址。 如果不感兴趣,将该参数置零。最后如果需要知道死线程的退出码,应当指出接 收该错误码的地址。
一个线程可以通过以下的代码等待所有的非守护线程结束:
while(thr_join(0,0,0)==0)
第三个参数的声明(void **)看上去很奇怪。相应的thr_exit()的参数为 void *。这样做的意图在于你的错误代码为定长的四字节,c语言给定长4字节的 定义不能是void型,因为这以为着没有参数。所以用void*。因为thr_join()的 第三参数必须是一个指向thr_exit()返回值的指针,所以类型必须是void **。
注意,thr_join()只在目标线程为非分离时有效。如果没有特殊的同步要求 的话,线程一般都设置成分离的。
可以认为,分离线程是通常意义下的线程,而非分离线程知识特殊情况。

2.1.9简单的例程

在例子2-1里,一个运行在顶部的线程,创建一个辅助线程来执行fetch过程, 这个辅助过程涉及到复杂的数据库查询,需要较长的时间。主线程在等待结果的 时候还有其他事情可做。所以它通过执行thr_join()来等待辅助过程结束。
操作结果被当作堆栈参数传送,因为主线程等待spun-off线程结束。在一般 意义上,用malloc()存储数据比通过线程的堆栈来存储要好一些。????
Code Example 2-1 A Simple Threads Program
Void mainline(){

Char int result;
Thread_t helper;
Int status;

Thr_create(0,0,fetch,&result,0,&helper);
/* do something else for a while */
Thr_join(helper,0,&status);
/* it's now safe to use result*/
}
void fetch(int * result){
/*fetch value from a database */
*result=value;
thr_exit(0);
}

2.1.10维护线程专有数据

单线程C程序有两种基本数据--本地数据和全局数据。多线程C程序增加了 一个特殊类型--线程专有数据(TSD)。非常类似与全局数据,只不过它是线程 私有的。
TSD是以线程为界限的。TSD是定义线程私有数据的唯一方法。每个线程专有 数据项都由一个进程内唯一的关键字(KEY)来标识。用这个关键字,线程可以 来存取线程私有的数据。
维护TSD的方法通过以下三个函数进行:
· thr_keycreate()--创建关键字
· thr_setspecific()--将一个线程绑定在一个关键字上
· thr_getspecific()--存储指定地址的值

2.1.10.1 thr_keycreate(3T)
thr_keycreate()在进程内部分配一个标识TSD的关键字。关键字是进程内部唯一的,所有线程在创建时的关键字值是NULL。
一旦关键字被建立,每一个线程可以为关键字绑定一个值。这个值对于绑定的线程来说是唯一的,被每个线程独立维护。
#include
int thr_keycreate(thread_key_t keyp,
void (*destructor)(void *value);
如果thr_keycreate()成功返回,分配的关键字被存储在由keyp指向的区 域里。调用者一定要保证存储和对关键字的访问被正确地同步。
一个可选的析构函数,destructor,可以和每个关键字联系起来。如果一 个关键字的destructor不空而且线程给该关键字一个非空值,在线程退出时该 析构函数被调用,使用当前的绑定值。对于所有关键字的析构函数执行的顺序 是不能指定的。
返回值--thr_keycreate()

上一页  [1] [2] [3] [4] [5]  下一页

[数据载入中...] [返回上一页] [打 印]