Pthread_once and pthread_key

Source: Internet
Author: User
Tags posix

One-time Initialization

Sometimes we need to initialize some POSIX variables only once, such as the thread key (as I will discuss below ). If we initialize the program multiple times, an error will occur.

In traditional sequential programming, Boolean variables are often used for one-time initialization. The control variable is statically initialized to 0, and any code dependent on the initialization can test the variable. If the variable value is still 0, it can initialize and set the variable to 1. The code to be checked later will skip initialization.

But in multi-threaded programming, things become more complicated. If multiple threads concurrently execute the initialization sequence code, two threads may find that the control variable is 0 and all initialization is performed. This process should have been executed only once.

If we need to initialize a static POSIX variable, we can use a mutex to control the initial state of the variable. But sometimes we need to perform dynamic initialization of this variable, and pthread_once will be much more convenient.

Original function:

Pthread_once_t once_control = pthread_once_init;

Int pthread_once (pthread_once_t * once_control, void (* init_routine) (void ));

Parameters:

Once_control control variable

Init_routine initialization Function

Return Value:

If 0 is returned, the error number is returned.

A variable of the type pthread_once_t is a control variable. The control variable must be statically initialized using the pthread_once_init macro.

The pthread_once function first checks the control variable to determine whether Initialization is complete. If Initialization is complete, it simply returns. Otherwise, pthread_once calls the initialization function and records that the initialization is complete. If another thread calls pthread_once at the beginning of a thread, the call thread waits until the ready-made Initialization is completed.

The program example of this function is as follows:

# Include <pthread. h>

Pthread_once_t once = pthread_once_init;

Pthread_mutex_t mutex;

Void once_init_routine (void)

{

Int status;

Status = pthread_mutex_init (& mutex, null );

If (status = 0)

Printf ("init success !, My ID is % u ", pthread_self ());

}

Void * child_thread (void * Arg)

{

Printf ("I'm child, my ID is % u", pthread_self ());

Pthread_once (& once, once_init_routine );

}

Int main (INT argc, char * argv [])

{

Pthread_t child_thread_id;

Pthread_create (& child_thread_id, null, child_thread, null );

Printf ("I'm Father, my ID is % u", pthread_self ());

Pthread_once (& once_block, once_init_routine );

Pthread_join (child_thread_id, null );

}

Private Data of the thread

All threads in a process share the same address space. Any variables declared as static or external variables or declared in the process heap can be read and written by all threads in the process. So how can we make the wire program have its own private data.

POSIX provides a way to create a thread key.

Original function:

Int pthread_key_create (pthread_key * Key, void (* destructor) (void *));

Parameters:

Key private data key

Destructor cleanup function

Return Value:

If the result is successful, 0 is returned. If the result fails, the error number is returned.

The first parameter is a pointer to a key value, and the second parameter specifies a destructor function (cleaning function). If this parameter is not blank, when each thread ends, the system will call this function to release the memory block bound to this key. This function is often used with the function pthread_once. In order to make this key be created only once. The pthread_once function declares an initialization function. When pthread_once is called for the first time, it executes this function and will be ignored in future calls.

The following is a program example:

# Include <pthread. h>

Pthread_key_t tsd_key;

Pthread_once_t key_once = pthread_once_init;

Void once_routine (void)

{

Int status;

Status = pthread_key_create (& tsd_key, null );

If (status = 0)

Printf ("Key create success! My ID is % u/N ", pthread_self ());

}

Void * child_thread (void * Arg)

{

Printf ("I'm child, my ID is % u/N", pthread_self ());

Pthread_once (& key_once, once_routine );

}

Int main (INT argc, char * argv [])

{

Pthread_t child_thread_id;

Pthread_create (& child_thread_id, null, child_thread, null );

Printf ("I'm Father, my ID is % u/N", pthread_self ());

Pthread_once (& key_once, once_routine );

}

One-time Initialization

Sometimes we need to initialize some POSIX variables only once, such as the thread key (as I will discuss below ). If we initialize the program multiple times, an error will occur.

In traditional sequential programming, Boolean variables are often used for one-time initialization. The control variable is statically initialized to 0, and any code dependent on the initialization can test the variable. If the variable value is still 0, it can initialize and set the variable to 1. The code to be checked later will skip initialization.

But in multi-threaded programming, things become more complicated. If multiple threads concurrently execute the initialization sequence code, two threads may find that the control variable is 0 and all initialization is performed. This process should have been executed only once.

If we need to initialize a static POSIX variable, we can use a mutex to control the initial state of the variable. But sometimes we need to perform dynamic initialization of this variable, and pthread_once will be much more convenient.

Original function:

Pthread_once_t once_control = pthread_once_init;

Int pthread_once (pthread_once_t * once_control, void (* init_routine) (void ));

Parameters:

Once_control control variable

Init_routine initialization Function

Return Value:

If 0 is returned, the error number is returned.

A variable of the type pthread_once_t is a control variable. The control variable must be statically initialized using the pthread_once_init macro.

The pthread_once function first checks the control variable to determine whether Initialization is complete. If Initialization is complete, it simply returns. Otherwise, pthread_once calls the initialization function and records that the initialization is complete. If another thread calls pthread_once at the beginning of a thread, the call thread waits until the ready-made Initialization is completed.

The program example of this function is as follows:

# Include <pthread. h>

Pthread_once_t once = pthread_once_init;

Pthread_mutex_t mutex;

Void once_init_routine (void)

{

Int status;

Status = pthread_mutex_init (& mutex, null );

If (status = 0)

Printf ("init success !, My ID is % u ", pthread_self ());

}

Void * child_thread (void * Arg)

{

Printf ("I'm child, my ID is % u", pthread_self ());

Pthread_once (& once, once_init_routine );

}

Int main (INT argc, char * argv [])

{

Pthread_t child_thread_id;

Pthread_create (& child_thread_id, null, child_thread, null );

Printf ("I'm Father, my ID is % u", pthread_self ());

Pthread_once (& once_block, once_init_routine );

Pthread_join (child_thread_id, null );

}

Private Data of the thread

All threads in a process share the same address space. Any variables declared as static or external variables or declared in the process heap can be read and written by all threads in the process. So how can we make the wire program have its own private data.

POSIX provides a way to create a thread key.

Original function:

Int pthread_key_create (pthread_key * Key, void (* destructor) (void *));

Parameters:

Key private data key

Destructor cleanup function

Return Value:

If the result is successful, 0 is returned. If the result fails, the error number is returned.

The first parameter is a pointer to a key value, and the second parameter specifies a destructor function (cleaning function). If this parameter is not blank, when each thread ends, the system will call this function to release the memory block bound to this key. This function is often used with the function pthread_once. In order to make this key be created only once. The pthread_once function declares an initialization function. When pthread_once is called for the first time, it executes this function and will be ignored in future calls.

The following is a program example:

# Include <pthread. h>

Pthread_key_t tsd_key;

Pthread_once_t key_once = pthread_once_init;

Void once_routine (void)

{

Int status;

Status = pthread_key_create (& tsd_key, null );

If (status = 0)

Printf ("Key create success! My ID is % u/N ", pthread_self ());

}

Void * child_thread (void * Arg)

{

Printf ("I'm child, my ID is % u/N", pthread_self ());

Pthread_once (& key_once, once_routine );

}

Int main (INT argc, char * argv [])

{

Pthread_t child_thread_id;

Pthread_create (& child_thread_id, null, child_thread, null );

Printf ("I'm Father, my ID is % u/N", pthread_self ());

Pthread_once (& key_once, once_routine );

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.