有些事需要且只能執行一次(比如互斥量初始化)。
通常當初始化應用程序時,可以比較容易地將其放在main函數中。但當你寫一個庫函數時,就不能在main里面初始化了,你可以用靜態初始化,但使用一次初始(pthread_once_t
)會比較容易些。
首先要定義一個pthread_once_t
變量,這個變量要用宏PTHREAD_ONCE_INIT
初始化。然后創建一個與控制變量相關的初始化函數。
pthread_once_t once_control = PTHREAD_ONCE_INIT;
void init_routine()
{
//初始化互斥量
//初始化讀寫鎖
......
}
接下來就可以在任何時刻調用pthread_once
函數
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void));
功能:本函數使用初值為PTHREAD_ONCE_INIT
的once_control
變量保證init_routine()
函數在本進程執行序列中僅執行一次。在多線程編程環境下,盡管pthread_once()
調用會出現在多個線程中,init_routine()
函數僅執行一次,究竟在哪個線程中執行是不定的,是由內核調度來決定。
Linux Threads使用互斥鎖和條件變量保證由pthread_once()
指定的函數執行且僅執行一次。
實際"一次性函數"的執行狀態有三種:NEVER(0)
、IN_PROGRESS(1)
、DONE (2)
,用once_control
來表示pthread_once()
的執行狀態:
1、如果once_control
初值為0,那么pthread_once
從未執行過,init_routine()
函數會執行。
2、如果once_control
初值設為1,則由于所有pthread_once()
都必須等待其中一個激發"已執行一次"信號, 因此所有pthread_once ()
都會陷入永久的等待中,init_routine()
就無法執行
3、如果once_control
設為2,則表示pthread_once()
函數已執行過一次,從而所有pthread_once()
都會立即 返回,init_routine()
就沒有機會執行
當pthread_once
函數成功返回,once_control
就會被設置為2
例子:將互斥量一次性初始化,使用pthread_once來實現
/*
DESCRIPTION: 一次性初始化
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void));
如果once_control為0,init_routine()就會執行
pthread_once()成功返回之后,once_control會變為2
*/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_t tid;
void thread_init()
{
printf("I'm in thread 0x%x\n", tid);
}
void *thread_fun1(void *arg)
{
tid = pthread_self();
printf("I'm thread 0x%x\n", tid);
printf("once is %d\n", once);
pthread_once(&once, thread_init);
printf("once is %d\n", once);
return NULL;
}
void *thread_fun2(void *arg)
{
sleep(2);
tid = pthread_self();
printf("I'm thread 0x%x\n", tid);
pthread_once(&once, thread_init);
return NULL;
}
int main()
{
pthread_t tid1, tid2;
int err;
err = pthread_create(&tid1, NULL, thread_fun1, NULL);
if(err != 0)
{
printf("create new thread 1 failed\n");
return ;
}
err = pthread_create(&tid2, NULL, thread_fun2, NULL);
if(err != 0)
{
printf("create new thread 1 failed\n");
return ;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
gcc -o thread_once -lpthread thread_once.c