[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

General Programming Concepts: Writing and Debugging Programs

Creating Threads

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.

Read the following to learn more about creating threads:

Thread Attributes Object

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.

Thread Attributes Object Creation and Destruction

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 */
                /* 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.

Detachstate Attribute

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.

Other Attributes

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.

Contention Scope Specifies the contention scope of a thread.
Inheritsched Specifies the inheritance of scheduling properties of a thread.
Schedparam Specifies the scheduling parameters of a thread.
Schedpolicy Specifies the scheduling policy of a thread.

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.

Thread Creation

Creating a thread is accomplished by calling the pthread_create subroutine. This subroutine creates a new thread and makes it runnable.

Using the Thread Attributes Object

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_create(&thread, &attr, init_routine, NULL);

is equivalent to:

pthread_t thread;
pthread_create(&thread, NULL, init_routine, NULL);

Entry Point Routine

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 Synchronization Overview for more information about using this pointer.

Returned Information

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.

Handling Thread IDs

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.

A First Multi-Threaded Program

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);

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)
        rc = pthread_create(&f_th, NULL, Thread, (void *)f_str);
        if (rc)
        /* usually the exit subroutine should not be used
           see below to get more information */

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.

Related Information

Understanding Threads

Threads Basic Operation Overview

Terminating Threads

List of Threads Basic Operation Subroutines

Threads Library Options

[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]