日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2.5 lazy initialization

發(fā)布時間:2024/3/7 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2.5 lazy initialization 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 保護(hù)共享數(shù)據(jù)的初始化過程
  • std::call_once
  • std::call_once 的替代方案


保護(hù)共享數(shù)據(jù)的初始化過程

lazy initialization (延遲初始化)在單線程的代碼中是很常見的。譬如一個共享數(shù)據(jù)的初始化構(gòu)建可能會消耗較多的資源,那么對它的每次操作都需要先對它進(jìn)行檢查,如果它已經(jīng)被初始化了,那么就可以直接使用而不是重新再初始化它。

例如,打開一個文件可能需要消耗較多的資源,如果它已經(jīng)被打開,那么我們就不需要再次 open 了。

上面的例子并不是線程安全的。在并發(fā)代碼中假設(shè)有A和B兩個線程,當(dāng) A 線程發(fā)現(xiàn)文件沒有被打開然后打開文件往里寫數(shù)據(jù)時,B 線程此時應(yīng)該是不能夠打開文件的,但在 B 線程看來,文件確實(shí)是被打開了的,因此只要 B 線程搶占到鎖,那么它就會往文件里寫數(shù)據(jù)。

因此,打開文件的這一步,需要用互斥量保護(hù)起來。

從上面的結(jié)果我們可以看到,我們所做的修改依然不是線程安全的。因?yàn)楫?dāng)線程 A 打開文件后,離開了 mtxFile 的保護(hù)域時,線程 B 可能在這個時候拿到了 mtxFile 然后打開文件。為此,我們需要將 is_open 也加入鎖的范圍內(nèi)

可以看到,上面的這份代碼就是線程安全的?,F(xiàn)在我們考慮性能上的問題。我們頻繁地創(chuàng)建鎖并加鎖解鎖操作會消耗大量的系統(tǒng)資源,C++標(biāo)準(zhǔn)庫為此提供了較好的解決方案。


std::call_once

與 std::call_once 相適配的是 std::once_flag,它會比互斥量消耗的資源更少,特別是當(dāng)初始化完成以后。

  • std::mutex 和 std::once_flag 對象不能拷貝和移動。

于是,方案修改為:

使用 std::call_once 可以確保 lambda 表達(dá)式在并發(fā)程序中只會被一個線程調(diào)用一次,這就是我們所說的 lazy initialization。

通常,我們也會將 std::call_once 和要保護(hù)的數(shù)據(jù)放在一個類中,用來延遲初始化。借用書中的代碼:

在本例中,第一次調(diào)用 send_data 和 receive_data 時會完成線程的初始化。


std::call_once 的替代方案

在只需要一個全局實(shí)例的情況下,多線程可以安全地調(diào)用 getInstance 函數(shù),不用擔(dān)心數(shù)據(jù)競爭。

總結(jié)

以上是生活随笔為你收集整理的2.5 lazy initialization的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。