有些事需要且只能執(zhí)行一次(比如互斥量初始化)。
通常當(dāng)初始化應(yīng)用程序時(shí),可以比較容易地將其放在main函數(shù)中。但當(dāng)你寫一個(gè)庫函數(shù)時(shí),就不能在main里面初始化了,你可以用靜態(tài)初始化,但使用一次初始(pthread_once_t)會(huì)比較容易些。
首先要定義一個(gè)pthread_once_t變量,這個(gè)變量要用宏PTHREAD_ONCE_INIT初始化。然后創(chuàng)建一個(gè)與控制變量相關(guān)的初始化函數(shù)。
pthread_once_t once_control = PTHREAD_ONCE_INIT;
void init_routine()
{
//初始化互斥量
//初始化讀寫鎖
......
}
接下來就可以在任何時(shí)刻調(diào)用pthread_once函數(shù)
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void));
功能:本函數(shù)使用初值為PTHREAD_ONCE_INIT的once_control變量保證init_routine()函數(shù)在本進(jìn)程執(zhí)行序列中僅執(zhí)行一次。在多線程編程環(huán)境下,盡管pthread_once()調(diào)用會(huì)出現(xiàn)在多個(gè)線程中,init_routine()函數(shù)僅執(zhí)行一次,究竟在哪個(gè)線程中執(zhí)行是不定的,是由內(nèi)核調(diào)度來決定。
Linux Threads使用互斥鎖和條件變量保證由pthread_once()指定的函數(shù)執(zhí)行且僅執(zhí)行一次。
實(shí)際"一次性函數(shù)"的執(zhí)行狀態(tài)有三種:NEVER(0)、IN_PROGRESS(1)、DONE (2),用once_control來表示pthread_once()的執(zhí)行狀態(tài):
1、如果once_control初值為0,那么pthread_once從未執(zhí)行過,init_routine()函數(shù)會(huì)執(zhí)行。
2、如果once_control初值設(shè)為1,則由于所有pthread_once()都必須等待其中一個(gè)激發(fā)"已執(zhí)行一次"信號(hào), 因此所有pthread_once ()都會(huì)陷入永久的等待中,init_routine()就無法執(zhí)行
3、如果once_control設(shè)為2,則表示pthread_once()函數(shù)已執(zhí)行過一次,從而所有pthread_once()都會(huì)立即 返回,init_routine()就沒有機(jī)會(huì)執(zhí)行
當(dāng)pthread_once函數(shù)成功返回,once_control就會(huì)被設(shè)置為2
例子:將互斥量一次性初始化,使用pthread_once來實(shí)現(xiàn)
/*
DESCRIPTION: 一次性初始化
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void));
如果once_control為0,init_routine()就會(huì)執(zhí)行
pthread_once()成功返回之后,once_control會(huì)變?yōu)?
*/
#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