创建线程
线程创建和进程创建不同,因为在线程之间不存在父子关系。
所有线程(除了创建进程时自动被创建的初始线程)都在相同的层次级别上。 线程并不维护已创建线程的列表,也不知道创建它的线程。
创建线程时,必须指定入口点例程和参数。 每个线程有带有一个参数的入口点例程。 同一个入口点例程可能被多个线程使用。
线程具有属性,用于指定线程的特征。 要控制线程属性,必须在创建线程之前定义线程属性对象。
线程属性对象
线程属性被存储在不透明对象线程属性对象中,在创建线程时使用。 它包含多个属性,这取决于 POSIX 选项的实现。 通过类型为 pthread_attr_t的变量访问该对象。 在AIX 中,pthread_attr_t数据类型是指向结构体的指针;在其他系统中,它可能是结构体或其他数据类型。
创建和破坏线程属性对象
o
线程属性对象由 pthread_attr_init 子例程初始化为缺省值。 这些属性由子例程处理。 线程属性对象被 pthread_attr_destroy 子例程破坏。 此子例程能够释放 pthread_attr_init 子例程动态分配的存储空间,这取决于线程库的实现。
在下面的示例中,创建线程属性对象并将其初始化为缺省值,然后使用该对象,最终删除它:
pthread_attr_t attributes;
/* the attributes object is created */
...
if (!pthread_attr_init(&attributes)) {
/* the attributes object is initialized */
...
/* using the attributes object */
...
pthread_attr_destroy(&attributes);
/* the attributes object is destroyed */
}同一个属性对象能用来创建多个线程。 在创建两个线程之间也能修改它。 当创建线程后,可以删除属性对象而不影响由它创建的线程。
Detachstate 属性
始终定义以下属性:
- Detachstate
- 指定线程的已拆离状态。
该属性的值由 pthread_attr_get自治区 子例程返回; 它可以由 pthread_attr_set拆卸状态 子例程设置。 此属性的可能值为下面的符号常量:
- PTHREAD_CREATE_DETACHED
- 指定将在已拆离状态创建线程
- PTHREAD_CREATE_JOINABLE
- 指定在可连接状态创建线程
缺省值为 PTHREAD_CREATE_JOINABLE。
如果您在可连接状态创建线程,您必须对线程调用 pthread_join 子例程。 否则,创建新线程时,您可能耗尽存储空间,因为每个线程都会占用大量内存。 有关 pthread_join 子例程的更多信息,请参阅 调用 pthread_join 子例程。
其他线程属性
AIX 还定义了以下属性,这些属性适用于高级程序,并且可能需要特殊执行特权才能生效。 使用缺省设置,大多数程序能够正确运行。 使用继承的属性 中说明了如何使用以下属性。
- 争用作用域
- 指定线程的争用作用域
- Inheritsched
- 指定线程的调度属性的继承
- Schedparam
- 指定线程的调度参数
- Schedpolicy
- 指定线程的调度策略
堆栈属性中说明了如何使用以下堆栈属性。
- Stacksize
- 指定线程的堆栈大小
- Stackaddr
- 指定线程的堆栈地址
- Guardsize
- 指定线程的堆栈保护区大小
使用 pthread_create 子例程创建线程
通过调用 pthread_create 子例程来创建线程。 此子例程创建新线程并使其能够运行。
使用线程属性对象
调用 pthread_create 子例程时,您可以指定线程属性对象。 如果您指定了 NULL 指针,被创建的线程将具有缺省属性。 因而,以下代码片段:
pthread_t thread;
pthread_attr_t attr;
...
pthread_attr_init(&attr);
pthread_create(&thread, &attr, init_routine, NULL);
pthread_attr_destroy(&attr);pthread_t thread;
...
pthread_create(&thread, NULL, init_routine, NULL);入口点例程
在调用 pthread_create 子例程时,您必须指定入口点例程。 您的程序提供的例程与进程的 main 例程相似。 它是新线程执行的第一个用户例程。 当线程从其例程返回时,线程被自动终止。
入口点例程有一个参数(空指针),它是在调用 pthread_create 子例程时指定的。 您可以指定指向某些数据(例如:字符串或者结构)的指针。 创建线程(调用 pthread_create 子例程的线程)和被创建线程必须在此指针的实际类型上保持一致。
入口点例程返回空指针。 在线程终止之后,线程库将存储此指针,除非线程已拆离。 有关使用此指针的更多信息,请参阅 从线程返回信息。
返回的信息
pthread_create 子例程返回新线程的线程标识。 调用程序能够使用此线程标识在线程上执行各种操作。
根据两个线程的调度参数,新线程可能在对 pthread_create 子例程的调用返回之前就开始运行。 甚至可能当 pthread_create 子例程返回时,新线程已经被终止。 这时 pthread_create 子例程通过 thread 参数返回的线程标识已经无效。 因此检查使用线程标识作为参数的线程库子例程返回的 ESRCH 错误代码很重要。
如果 pthread_create 子例程不成功,那么不创建新线程, thread 参数中的线程标识为无效且返回适当的错误代码。 有关更多信息,请参阅 多线程程序示例。
处理线程标识
新创建的线程的线程标识通过 thread 参数被返回给创建线程。 当前线程标识由 pthread_self 子例程返回。
线程标识是不透明对象; 其类型为 pthread_t。 在 AIX中, pthread_t 数据类型是整数。 在其他系统上,可能是结构、指针或者其他数据类型。
要改善使用线程库的程序的可移植性,应该始终将线程标识作为非透明对象处理。 因此,应该使用 pthread_equal 子例程来比较线程标识。 请不要使用 C 等于运算符 (==),因为 pthread_t 数据类型不可为算术类型或者指针。