線程高級(jí):一次性初始化

有些事需要且只能執(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_INITonce_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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自:Youtherhttps://www.cnblogs.com/youtherhome/archive/201...
    njukay閱讀 1,724評(píng)論 0 52
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2、Andro...
    隔壁老李頭閱讀 9,715評(píng)論 8 13
  • 簡介 線程創(chuàng)建 線程屬性設(shè)置 線程參數(shù)傳遞 線程優(yōu)先級(jí) 線程的數(shù)據(jù)處理 線程的分離狀態(tài) 互斥鎖 信號(hào)量 一 線程創(chuàng)...
    第八區(qū)閱讀 8,713評(píng)論 1 6
  • 創(chuàng)建線程 C99新增restrict用于限定指針;該關(guān)鍵字用于告訴編譯器,所有修改該指針?biāo)赶虻膬?nèi)容的操作全部都是...
    Joe_HUST閱讀 994評(píng)論 0 0
  • 線程 在linux內(nèi)核那一部分我們知道,線程其實(shí)就是一種特殊的進(jìn)程,只是他們共享進(jìn)程的文件和內(nèi)存等資源,無論如何對(duì)...
    大雄good閱讀 718評(píng)論 0 2

友情鏈接更多精彩內(nèi)容