A thread has attributes, which specify the characteristics of the thread. The attributes default values fit for most common cases. To control thread attributes, a thread attributes object must be defined before creating the thread.
The thread attributes are stored in an opaque object, the thread attributes object, used when creating the thread. It contains several attributes, depending on the implementation of POSIX options. It is accessed through a variable of type pthread_attr_t. In AIX, the pthread_attr_t data type is a pointer to a structure; on other systems it may be a structure or another data type.
The thread attributes object is initialized to default values by the pthread_attr_init subroutine. The attributes are handled by subroutines. The thread attributes object is destroyed by the pthread_attr_destroy subroutine. This subroutine may free storage dynamically allocated by the pthread_attr_init subroutine, depending on the implementation of the threads library.
In the following example, a thread attributes object is created and initialized with default values, then used and finally destroyed:
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 */ }
The same attributes object can be used to create several threads. It can also be modified between two thread creations. When the threads are created, the attributes object can be destroyed without affecting the threads created with it.
The following attribute is always defined.
Detachstate | Specifies the detached state of a thread. |
The value of the attribute is returned by the pthread_attr_getdetachstate subroutine; it can be set by the pthread_attr_setdetachstate subroutine. Possible values for this attributes are the following symbolic constants:
PTHREAD_CREATE_DETACHED | Specifies that the thread will be created in the detached state. |
PTHREAD_CREATE_JOINABLE | Specifies that the thread will be created in the joinable state. |
The default value is PTHREAD_CREATE_JOINABLE.
If you create a thread in the joinable state, you must pthread_join (Calling the pthread_join Subroutine) with the thread. Otherwise, you may run out of storage space when creating new threads, because each thread takes up a signficant amount of memory.
The following attributes are also defined in AIX. They are intended for advanced programs and may require special execution privilege to take effect. Most programs will operate correctly with the default settings.
The use of these attributes is explained in Scheduling Attributes.
Stacksize | Specifies the size of the thread's stack. |
Stackaddr | Specifies the address of the thread's stack. |
Guardsize | Specifies the size of the guard area of the thread's stack. |
The use of these attributes is explained in Stack Attributes.
Creating a thread is accomplished by calling the pthread_create subroutine. This subroutine creates a new thread and makes it runnable.
When calling the pthread_create subroutine, you may specify a thread attributes object. If you specify a NULL pointer, the created thread will have the default attributes. Thus, the code fragment:
pthread_t thread; pthread_attr_t attr; ... pthread_attr_init(&attr); pthread_create(&thread, &attr, init_routine, NULL); pthread_attr_destroy(&attr);
is equivalent to:
pthread_t thread; ... pthread_create(&thread, NULL, init_routine, NULL);
When calling the pthread_create subroutine, you must specify an entry-point routine. This routine, provided by your program, is similar to the main routine for the process. It is the first user routine executed by the new thread. When the thread returns from this routine, the thread is automatically terminated.
The entry-point routine has one parameter, a void pointer, specified when calling the pthread_create subroutine. You may specify a pointer to some data, such as a string or a structure. The creating thread (the one calling the pthread_create subroutine) and the created thread must agree upon the actual type of this pointer.
The entry-point routine returns a void pointer. After the thread termination, this pointer is stored by the threads library unless the thread is detached. See Returning Information from a Thread for more information about using this pointer.
The pthread_create subroutine returns the thread ID of the new thread. The caller can use this thread ID to perform various operations on the thread.
Depending on the scheduling parameters of both threads, the new thread may start running before the call to the pthread_create subroutine returns. It may even happen that, when the pthread_create subroutine returns, the new thread has already terminated. The thread ID returned by the pthread_create subroutine through the thread parameter is then already invalid. It is, therefore, important to check for the ESRCH error code returned by threads library subroutines using a thread ID as a parameter.
If the pthread_create subroutine is unsuccessful, no new thread is created, the thread ID in the thread parameter is invalid, and the appropriate error code is returned.
The thread ID of a newly created thread is returned to the creating thread through the thread parameter. The current thread ID is returned by the pthread_self subroutine.
A thread ID is an opaque object; its type is pthread_t. In AIX, the pthread_t data type is an integer. On other systems, it may be a structure, a pointer, or any other data type.
To enhance the portability of programs using the threads library, the thread ID should always be handled as an opaque object. For this reason, thread IDs should be compared using the pthread_equal subroutine. Never use the C equality operator (==), because the pthread_t data type may be neither an arithmetic type nor a pointer.
The first multi-threaded program discussed is short. It displays "Hello!" in both English and French for five seconds. Compile with cc_r or xlc_r. See Developing Multi-Threaded Programs for more information on compiling thread programs.
#include <pthread.h> /* include file for pthreads - the 1st */ #include <stdio.h> /* include file for printf() */ #include <unistd.h> /* include file for sleep() */
void *Thread(void *string) { while (1) printf("%s\n", (char *)string); pthread_exit(NULL); }
int main() { char *e_str = "Hello!"; char *f_str = "Bonjour !"; pthread_t e_th; pthread_t f_th; int rc; rc = pthread_create(&e_th, NULL, Thread, (void *)e_str); if (rc) exit(-1); rc = pthread_create(&f_th, NULL, Thread, (void *)f_str); if (rc) exit(-1); sleep(5); /* usually the exit subroutine should not be used see below to get more information */ exit(0); }
The initial thread (executing the main routine) creates two threads. Both threads have the same entry-point routine (the Thread routine), but a different parameter. The parameter is a pointer to the string that will be displayed.