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