国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

解開C++之call_once的神秘面紗:記一個有意思的問題筆記

開發 前端
最近因為項目要求用C++,項目中需要一個接口只調用一次,需要使用到C++的call_once機制,于是寫一個小demo來測試,就因為這個足夠小發現了一個非常有意思的問題。

引言

最近因為項目要求用c++,之前一直很討厭c++,沒辦法只能短時間彌補c++的知識,項目中需要一個接口只調用一次,需要使用到c++的call_once機制,于是寫一個小demo來測試,就因為這個足夠小發現了一個非常有意思的問題。

call_once,基本原理

std::call_once 的內部實現基于兩個重要的組件:std::once_flag 和 std::invoke。std::once_flag 是一個標志,用于表示某個函數是否已經被調用過。而 std::invoke 則負責實際調用該函數。

call_once的基本工作原理是:使用 std::once_flag 來標記函數是否被調用過。當有多個線程試圖調用 std::call_once 時,只有一個線程會執行函數,其他線程會被阻塞直至該函數執行完畢。

std::call_once 的使用步驟三步曲:

  • 創建 std::once_flag 對象:在需要保證函數只調用一次的地方創建一個 std::once_flag 對象。
  • 編寫需要執行一次的函數:編寫你想要確保只調用一次的函數。
  • 調用 std::call_once:在需要執行該函數的地方調用 std::call_once 并傳入 std::once_flag 和函數名稱。

demo問題引入

demo非常簡單,實現一個Init函數進行call_once調用,只調用一次的函數Initialize做一次打印處理,main中連續調用Init 4次,理論上來說我們執行結果只有一行打印,這也是我們的目的。

#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>

std::once_flag flag;

void Initialize()
{
        std::cout << "Run into Initialize.." << std::endl;
}

void Init()
{
        std::call_once(flag, Initialize);
}

int main(){
    Init();
    Init();
    Init();
    Init();

    return 0;
}

使用g++編譯,執行結果發現出錯了:

拋出了個異常,從call_once上的理解來說代碼實現應該是沒問題的。于是使用調試大法gdb,編譯+g后使用gdb調試發現了個有意思的:

使用gdb調試發現__gthread_active_ptr指針是0,然后繼續執行發現___gthread_once返回的__e為0,于是繼續執行if就拋了異常。__gthread_active_ptr這又是什么呢?

深入研究研究

怎么看呢?既然不知道是什么我一般的操作是先看預處理部分代碼,使用gcc -E參數來編譯出call_once.i文件。

g++ -E call_once.cpp -o call_once.i

打開call_once.i文件我發現main函數部分沒有什么特別之處,我們搜索call_once可以看到它的實現。

這段代碼中的 std::call_once 函數首先創建了一個可調用對象 __callable,這個對象會調用傳入的函數 __f,并傳入 __args 參數。然后,它將 __callable 的地址存儲到 __once_callable 變量中。

接下來,通過一個 lambda 表達式將 __callable 的調用封裝在 __once_call 中,這個 lambda 表達式會執行 __callable。

最后,使用底層線程庫的 __gthread_once 函數來確保 __once_call 只會執行一次,即保證傳入的函數 __f 只會被調用一次。

如果 __gthread_once 的返回值不為零,表示執行出現了錯誤,會通過 __throw_system_error 拋出系統錯誤。

既然是if(__e)后拋的異常,我們繼續看__gthread_once的實現,搜索__gthread_once關鍵字,找到其實現:

 11452 static inline int
 11453 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
 11454 {
 11455   if (__gthread_active_p ())
 11456     return __gthrw_pthread_once (__once, __func);
 11457   else
 11458     return -1;
 11459 }

這個函數可以看到執行了__gthread_active_p ,我們繼續找__gthread_active_p 的實現。

__gthread_active_p 是一個內聯函數,返回一個整數值。

static void const __gthread_active_ptr 是一個靜態指針常量,初始化為 __gthrw___pthread_key_create 函數的地址。

extension 是一個 GNU C 擴展,用于告知編譯器避免對某些表達式進行警告。在此處,它將地址轉換為 void類型,以避免類型不匹配的警告。

&__gthrw___pthread_key_create 可能是一個特定線程庫(如 POSIX 線程庫)內部的函數,用于創建線程特定數據的關鍵字。

函數返回 __gthread_active_ptr != 0,即如果該指針非空,則表明線程已激活(從指針命名上猜的)。

所以該函數用于指示線程是否被激活。不明白?我們繼續看__gthrw___pthread_key_create的定義。

11405 static __typeof(pthread_key_create) __gthrw___pthread_key_create __attribute__ ((__weakref__("__pthread_key_create")));

通過 attribute((weakref("__pthread_key_create"))),將 __gthrw___pthread_key_create 弱引用到 __pthread_key_create。

弱引用是一種機制,允許在鏈接過程中,如果存在 __pthread_key_create 的定義,則使用它。但如果找不到 __pthread_key_create,則允許 __gthrw___pthread_key_create 仍然存在,只不過它將保持為空或未定義狀態。

這里大致就明白了,總結一下,call_once內部實現中要找一個__pthread_key_create定義,如果不存在則返回空,即我們調試的時的指針給了0,從而引起異常。__pthread_key_create函數很明顯是線程函數。好,那我們在代碼中加上該函數調用試試看。在main開始增加如下:

int main(){
    pthread_key_t key;
    pthread_key_create(&key, NULL);
    Init();

編譯運行:

達到預期效果了!

所以整體分析一下,在 call_once 的內部實現中,檢測是否支持 __pthread_key_create 可能是為了確保在使用 call_once 進行線程同步時,能夠利用線程特定數據鍵來管理狀態或資源,確保其正確性和性能。如果當前環境不支持 __pthread_key_create,那么在多線程環境下可能無法有效地管理線程特定的狀態信息。

因此,檢測是否支持 __pthread_key_create 可能是 call_once 實現中的一種策略,用于在可能的情況下提供更好的線程安全性和性能。如果當前環境不支持這個特定的功能,可能會采用其他方式來實現 call_once,或者簡化其行為以確保程序在這樣的環境中仍能正確運行,盡管可能會犧牲一些特定的功能或性能。

我嘗試不使用__pthread_key_create,隨便調用一個pthread庫的api,比如pthread_create,或者pthread_mutex_init,調用可以全部傳遞空指針,結果依然是可以達到預期的。所以驗證也說明call_once內部通過弱引用庫函數來檢測當前是否支持多線程,如果不支持則拋出異常,所以使用前提必須是多線程環境。

總結

call_once 的魅力與注意事項:

std::call_once 提供了一種簡單而又強大的多線程同步方式,但在使用時也需注意一些細節。比如一定要確保程序是多線程調用,如果有多線程自然還要確保線程安全,避免潛在的死鎖和競態條件問題登。

責任編輯:趙寧寧 來源: 囧囧妹
相關推薦

2018-06-24 16:39:28

Tomcat異常線程

2020-12-12 13:50:16

云開發

2021-01-27 13:54:05

開發云原生工具

2024-05-20 01:10:00

Promise變量

2009-08-26 17:53:31

C# DropDown

2023-05-15 09:16:18

CSSCSS Mask

2011-06-22 09:43:01

C++

2024-03-18 08:14:07

SpringDAOAppConfig

2022-03-21 10:21:50

jQuery代碼模式

2020-03-10 14:59:16

oracle數據庫監聽異常

2009-02-16 19:33:09

2021-03-25 06:12:55

SVG 濾鏡CSS

2012-05-22 10:12:59

jQuery

2021-04-19 10:47:11

NettyDemoI

2022-06-15 07:21:47

鼠標指針交互效果CSS

2022-08-15 22:34:47

Overflow方向裁切

2023-11-28 12:19:49

C++函數指針

2021-02-20 16:01:26

Github前端開發

2015-03-12 10:46:30

代碼代碼犯罪

2022-05-20 07:36:02

LiveTerm工具
點贊
收藏

51CTO技術棧公眾號

国产一区国产精品| 国产成人精品福利一区二区三区| 欧美日韩国产在线播放| 天天射成人网| 668精品在线视频| 国产一级视频| 青草久久视频| 欧美福利视频在线观看| 亚洲伊人影院| 国产一区二区中文字幕免费看| 中文字幕一区二区三区欧美日韩| 91久久国产综合久久91精品网站 | 亚洲va欧美va国产va天堂影院| 新呦u视频一区二区| 韩国三级电影一区二区| 天天操天天爽天天射| 亚洲精品乱码久久久久| 青青草原av在线| 亚洲国产精品女人久久久 | 5252色成人免费视频| 天天天综合网| 中文字幕日韩精品久久| 亚洲另类在线一区| 草草草在线视频| 色先锋资源久久综合| 午夜无码国产理论在线| 国产精品黄页免费高清在线观看| 欧美xxxx在线| 国产成人精品av| 国产一区二区三区四区二区| 日本在线观看不卡| 奇米色777欧美一区二区| 中文av在线播放| 高清欧美性猛交xxxx| 99精品视频在线观看| 久久电影网站| aaa级精品久久久国产片| 国产精品二三区| 涩涩涩在线视频| 日本黄网免费一区二区精品| 亚洲欧美日本在线| 久久国产精品免费一区二区三区| 欧美国产日韩激情| 亚洲视频一二三区| 羞羞的视频在线看| 91在线免费网站| 午夜精品免费在线观看| 欧美日韩在线二区| 国产无套内射久久久国产| 亚洲成人xxx| 国产成人影院| 久久亚洲中文字幕无码| 亚洲第一页自拍| 亚洲视频狠狠| 蜜桃传媒在线观看免费进入| 欧洲日韩成人av| 亚洲成人福利片| 欧美91在线|欧美| 国产一区二区三区播放| 中国人与牲禽动交精品| 成人av在线一区二区三区| 国内在线视频| 男人插女人下面免费视频| 中文字幕日韩在线视频| 国产精品视频久久一区| 成人免费网址| 欧美在线播放一区| 欧美日韩中文另类| 激情综合网av| 99精品在免费线中文字幕网站一区 | 日本h片在线看| 国产一区二区三区视频免费| 午夜精彩国产免费不卡不顿大片| 一区 二区 三区| 一本—道久久a久久精品蜜桃| 久久影院模特热| 精品视频一区二区不卡| 国产综合久久久久久鬼色| youjizz欧美| 免费av在线电影| 国产伦精品一区二区三区视频孕妇| 亚洲一区二区三区视频在线播放| 国精品一区二区三区| 欧美男男激情freegay| 亚洲午夜在线观看| 亚洲新中文字幕| 精品视频全国免费看| 一区二区免费视频| 国产a视频精品免费观看| 午夜欧美理论片| 亚洲视频精选| 亚洲黄色免费av| 嫩草影院2018| 男女激情无遮挡| 日韩精品福利片午夜免费观看| 成人黄色免费片| 上原亚衣av一区二区三区| 91传媒视频在线播放| 国产精品色在线| 日韩午夜免费视频| www.久久东京| 91精品亚洲一区在线观看| av电影资源| 无码专区aaaaaa免费视频| 欧美专区福利在线| 亚洲精品国产综合久久| 欧美日韩亚洲91| 久久国产成人午夜av影院| 国内精品福利| 91精品日本| 欧美日韩国产综合视频| 欧美 日韩 国产精品| 国产日韩av在线| 97在线视频免费看| 午夜精品美女自拍福到在线| 欧美成人在线直播| 亚洲男人的天堂在线观看| 欧美天天在线| 黑人糟蹋人妻hd中文字幕| 日韩av片永久免费网站| 久久这里有精品视频| 久久精品福利视频| 欧美日韩成人在线观看| 伊人久久在线观看| 亚洲精品**中文毛片| 国产一区在线观看视频| 国产成人精品一区二区三区四区| 日韩精品一区二区久久| 欧美wwwww| 丝袜在线观看| 亚洲精华国产| 中文字幕在线二区| 日韩手机在线| 粗大黑人巨茎大战欧美成人| 成人四虎影院| 欧美天天视频| 一级特黄大欧美久久久| 久久久久久久一区二区三区| 伊人久久大香线蕉成人综合网| 一区 二区 三区| 91精品国产自产精品男人的天堂| 99re66热这里只有精品3直播 | 欧美中文字幕不卡| 日韩精品免费观看| 久久色在线播放| 亚洲a成v人在线观看| 久久99精品久久久久久秒播放器| 1024av视频| 动漫成人在线观看| 桃色一区二区| 色综合中文网| 91精品国产91久久久久游泳池| 免费观看成人性生生活片| 欧美裸体在线版观看完整版| 欧美成人激情| 亚洲另类一区二区| 精品视频一区二区三区免费| 国产午夜精品视频| 国产日韩欧美成人| 欧美性猛交久久久乱大交小说| 精品不卡在线| 亚洲一区二区三区成人在线视频精品 | 高潮久久久久久久久久久久久久 | 导航福利在线| 亚洲aⅴ网站| 成人三级伦理片| 色综合久久88| 三年中国国语在线播放免费| 草草视频在线观看| 久久精品久久久精品美女| 欧美日韩中文精品| 九色自拍视频在线观看| 香蕉成人影院| 国产98色在线|日韩| 不卡中文字幕av| 国产福利影院在线观看| 中文字幕日韩在线| 久久99国产精品久久| 91久久香蕉国产日韩欧美9色| www.久久久久久.com| 婷婷精品国产一区二区三区日韩| 一级毛片国产| 亚洲系列另类av| 成人美女在线视频| 日韩一区二区在线观看| 成人日韩在线电影| 成人18网站| 91精品久久久久久综合五月天| 成人免费小视频| 午夜精品久久久久久久久久久久久 | 每日在线更新av| 91这里只有精品| 黑人巨大精品| 日韩av中文字幕一区二区| 最近2019年日本中文免费字幕| 午夜老司机在线观看| 日韩欧美亚洲成人| 日韩在线视频免费观看| 麻豆乱码国产一区二区三区| 亚洲日本精品国产第一区|