Submit Search
Effective Modern C++ 勉強会#3 Item16
1 like
•
1,134 views
M
Mitsuru Kariya
Item 16: Make const member functions thread safe. SlideShare でもちゃんと読めるようにちょっとだけ編集しました。
Technology
Read more
1 of 61
Download now
Download to read offline
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
More Related Content
PPTX
Effective Modern C++勉強会#4 Item 17, 18資料
Ryo Igarashi
PDF
Effective Modern C++ 勉強会#3 Item 15
Mitsuru Kariya
PPTX
Effective Modern C++ 勉強会 Item 22
Keisuke Fukuda
PPTX
Emcpp0506
Takatoshi Kondo
PDF
templateとautoの型推論
MITSUNARI Shigeo
PDF
Effective Modern C++ 勉強会 Item26
Akihiro Nishimura
PDF
中3女子でもわかる constexpr
Genya Murakami
PDF
Effective Modern C++ 勉強会#1 Item3,4
Takashi Hoshino
Effective Modern C++勉強会#4 Item 17, 18資料
Ryo Igarashi
Effective Modern C++ 勉強会#3 Item 15
Mitsuru Kariya
Effective Modern C++ 勉強会 Item 22
Keisuke Fukuda
Emcpp0506
Takatoshi Kondo
templateとautoの型推論
MITSUNARI Shigeo
Effective Modern C++ 勉強会 Item26
Akihiro Nishimura
中3女子でもわかる constexpr
Genya Murakami
Effective Modern C++ 勉強会#1 Item3,4
Takashi Hoshino
What's hot
(20)
PDF
NumPyが物足りない人へのCython入門
Shiqiao Du
PDF
高速な倍精度指数関数expの実装
MITSUNARI Shigeo
PPTX
Effective Modern C++ Item 9 and 10
uchan_nos
PDF
組み込みでこそC++を使う10の理由
kikairoya
PDF
Constexpr 中3女子テクニック
Genya Murakami
PDF
Effective Modern C++ 勉強会#7 Item 27
Mitsuru Kariya
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
PPTX
Effective modern c++ 8
uchan_nos
PDF
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
digitalghost
PDF
Boost.Coroutine
melpon
PDF
CTF for ビギナーズ ネットワーク講習資料
SECCON Beginners
PDF
effective modern c++ chapeter36
Tatsuki SHIMIZU
PPTX
競技プログラミングのためのC++入門
natrium11321
PDF
すごい constexpr たのしくレイトレ!
Genya Murakami
PDF
ctypes拡張モジュール
Moriyoshi Koizumi
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
Fixstars Corporation
PDF
CRC-32
7shi
PPTX
C#/.NETがやっていること 第二版
信之 岩永
PDF
CTF for ビギナーズ バイナリ講習資料
SECCON Beginners
PDF
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
NumPyが物足りない人へのCython入門
Shiqiao Du
高速な倍精度指数関数expの実装
MITSUNARI Shigeo
Effective Modern C++ Item 9 and 10
uchan_nos
組み込みでこそC++を使う10の理由
kikairoya
Constexpr 中3女子テクニック
Genya Murakami
Effective Modern C++ 勉強会#7 Item 27
Mitsuru Kariya
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
Effective modern c++ 8
uchan_nos
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
digitalghost
Boost.Coroutine
melpon
CTF for ビギナーズ ネットワーク講習資料
SECCON Beginners
effective modern c++ chapeter36
Tatsuki SHIMIZU
競技プログラミングのためのC++入門
natrium11321
すごい constexpr たのしくレイトレ!
Genya Murakami
ctypes拡張モジュール
Moriyoshi Koizumi
ARM CPUにおけるSIMDを用いた高速計算入門
Fixstars Corporation
CRC-32
7shi
C#/.NETがやっていること 第二版
信之 岩永
CTF for ビギナーズ バイナリ講習資料
SECCON Beginners
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
Ad
Viewers also liked
(15)
PDF
Effective modern-c++#9
Tatsuki SHIMIZU
PDF
emc++ chapter32
Tatsuki SHIMIZU
PPTX
Effective modern C++ 勉強会 #3 Item 12
Keisuke Fukuda
PPTX
Effective Modern C++ study group Item39
Takatoshi Kondo
PPTX
Effective Modern C++勉強会#2 Item 11(,12)
Keisuke Fukuda
PDF
Effective Modern C++ 勉強会#6 Item25
Takashi Hoshino
PDF
Effective Modern C++ 勉強会#8 Item38
Takashi Hoshino
PDF
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
mooopan
PDF
Emcjp item33,34
MITSUNARI Shigeo
PDF
emcjp Item 42
MITSUNARI Shigeo
PDF
Emcjp item21
MITSUNARI Shigeo
PDF
Emcpp item31
mitsutaka_takeda
PDF
Emcpp item41
mitsutaka_takeda
PDF
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda
PPTX
Effective modern c++ 5
uchan_nos
Effective modern-c++#9
Tatsuki SHIMIZU
emc++ chapter32
Tatsuki SHIMIZU
Effective modern C++ 勉強会 #3 Item 12
Keisuke Fukuda
Effective Modern C++ study group Item39
Takatoshi Kondo
Effective Modern C++勉強会#2 Item 11(,12)
Keisuke Fukuda
Effective Modern C++ 勉強会#6 Item25
Takashi Hoshino
Effective Modern C++ 勉強会#8 Item38
Takashi Hoshino
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
mooopan
Emcjp item33,34
MITSUNARI Shigeo
emcjp Item 42
MITSUNARI Shigeo
Emcjp item21
MITSUNARI Shigeo
Emcpp item31
mitsutaka_takeda
Emcpp item41
mitsutaka_takeda
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda
Effective modern c++ 5
uchan_nos
Ad
Similar to Effective Modern C++ 勉強会#3 Item16
(20)
PDF
Hello Dark-Side C# (Part. 1)
Yuto Takei
PDF
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_23
PDF
Boost.Flyweight
gintenlabo
PPTX
.NET Core 2.x 時代の C#
信之 岩永
PDF
第2回勉強会スライド
koturn 0;
PDF
Javaセキュアコーディングセミナー東京第3回講義
JPCERT Coordination Center
PPTX
Stream2の基本
shigeki_ohtsu
PDF
Unity2015_No10_~UGUI&Audio~
CHY72
PDF
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
和弘 井之上
PPTX
本当にあった怖い話し Db編
Oda Shinsuke
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
PDF
asm.js x emscripten: The foundation of the next level Web games
Noritada Shimizu
PDF
xv6から始めるSPIN入門
Ryousei Takano
PDF
Move semantics
mitsutaka_takeda
PPTX
Build Node.js-WASM/WASI Tiny compiler with Node.js
mganeko
PPTX
冬のLock free祭り safe
Kumazaki Hiroki
PDF
今日からできる!簡単 .NET 高速化 Tips
Takaaki Suzuki
PDF
わんくま同盟大阪勉強会#61
TATSUYA HAYAMIZU
PPT
Altanative macro
Motohiro KOSAKI
PDF
スタート低レイヤー #0
Kiwamu Okabe
Hello Dark-Side C# (Part. 1)
Yuto Takei
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
y_taka_23
Boost.Flyweight
gintenlabo
.NET Core 2.x 時代の C#
信之 岩永
第2回勉強会スライド
koturn 0;
Javaセキュアコーディングセミナー東京第3回講義
JPCERT Coordination Center
Stream2の基本
shigeki_ohtsu
Unity2015_No10_~UGUI&Audio~
CHY72
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
和弘 井之上
本当にあった怖い話し Db編
Oda Shinsuke
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
asm.js x emscripten: The foundation of the next level Web games
Noritada Shimizu
xv6から始めるSPIN入門
Ryousei Takano
Move semantics
mitsutaka_takeda
Build Node.js-WASM/WASI Tiny compiler with Node.js
mganeko
冬のLock free祭り safe
Kumazaki Hiroki
今日からできる!簡単 .NET 高速化 Tips
Takaaki Suzuki
わんくま同盟大阪勉強会#61
TATSUYA HAYAMIZU
Altanative macro
Motohiro KOSAKI
スタート低レイヤー #0
Kiwamu Okabe
Recently uploaded
(11)
PDF
20250730_QiitaBash_LT登壇資料_PDC_Kurashina.pdf
pdckurashina
PDF
TaketoFujikawa_ComicComputing12th_inKumamoto
Matsushita Laboratory
PDF
LoRaWAN ウェザーステーションキット v3 -WSC3-L 日本語ユーザーマニュアル
CRI Japan, Inc.
PDF
第三世代 ウェザーステーションキット v3 ー WSC3-L 日本語カタログ
CRI Japan, Inc.
PDF
【学会聴講報告】CVPR2025からみるVision最先端トレンド / CVPR2025 report
Sony - Neural Network Libraries
PDF
VMUG Japan book vsan 20250515 CPU/Memory vSAN
Kazuhiro Sota
PPTX
2025_7_25_吉祥寺_設計ナイト_ADR運用におけるデータ利活用の考え方.pptx
ssuserfcafd1
PDF
20250726_Devinで変えるエンプラシステム開発の未来
Masaki Yamakawa
PDF
20250729_Devin-for-Enterprise
Masaki Yamakawa
PPTX
baserCMS『カスタムコンテンツ』徹底活用術〜あなただけの管理画面を自由自在に〜
Ryuji Egashira
PDF
MahiroYoshida_セリフに着目したキャラクタロール推定に関する基礎検討_sigcc12th2025
Matsushita Laboratory
20250730_QiitaBash_LT登壇資料_PDC_Kurashina.pdf
pdckurashina
TaketoFujikawa_ComicComputing12th_inKumamoto
Matsushita Laboratory
LoRaWAN ウェザーステーションキット v3 -WSC3-L 日本語ユーザーマニュアル
CRI Japan, Inc.
第三世代 ウェザーステーションキット v3 ー WSC3-L 日本語カタログ
CRI Japan, Inc.
【学会聴講報告】CVPR2025からみるVision最先端トレンド / CVPR2025 report
Sony - Neural Network Libraries
VMUG Japan book vsan 20250515 CPU/Memory vSAN
Kazuhiro Sota
2025_7_25_吉祥寺_設計ナイト_ADR運用におけるデータ利活用の考え方.pptx
ssuserfcafd1
20250726_Devinで変えるエンプラシステム開発の未来
Masaki Yamakawa
20250729_Devin-for-Enterprise
Masaki Yamakawa
baserCMS『カスタムコンテンツ』徹底活用術〜あなただけの管理画面を自由自在に〜
Ryuji Egashira
MahiroYoshida_セリフに着目したキャラクタロール推定に関する基礎検討_sigcc12th2025
Matsushita Laboratory
Effective Modern C++ 勉強会#3 Item16
1.
Effective Modern C++ 勉強会#3 Item
16 刈谷 満(@kariya_mitsuru) 2015/4/22
2.
Item 16: Make
const member functions thread safe. const メンバ関数を スレッドセーフにしよう
3.
Item 16: Make
const member functions thread safe. 例 多項式を表すクラス ⇒Polynomial その多項式の根を計算するメンバ関数 ⇒roots
4.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const; … }; 多項式の根を計算するメンバ関数は、多項式自体を変更しない ↓ const メンバ関数 根を保持するデータ構造 (“using” については Item 9 を参照)
5.
Item 16: Make
const member functions thread safe. 多項式の根の計算は高くつく。 ⇓ 必要なければ計算したくない。 でも 2 回以上は計算したくない。 ⇓ 最初に使われた時に計算しよう! 計算した根はキャッシュしよう!
6.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; };
7.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら…
8.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら… 根を計算してそれを rootVals に保存し…
9.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら… 根を計算してそれを rootVals に保存し… キャッシュを有効にする!
10.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: bool rootsAreValid{ false }; RootsType rootVals{}; }; キャッシュが有効じゃなかったら… 根を計算してそれを rootVals に保存し… キャッシュを有効にする! あれ? const メンバ関数じゃなかったっけ?
11.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; mutable! roots は概念的にはオブジェクトを変更しない(論理的 const 性) 詳しくはWebで!! Effective C++ 第3版、Item 3 参照
12.
Item 16: Make
const member functions thread safe. ところで、この Polynomial クラスのオブジェクトを複数スレッドで同時に使うと… Polynomial p; … スレッド2 auto valsGivingZero = p.roots(); スレッド1 auto rootsOfP = p.roots(); const メンバ関数だから読むだけだし、 同期しなくても大丈夫っしょ!!
13.
Item 16: Make
const member functions thread safe. ところで、この Polynomial クラスのオブジェクトを複数スレッドで同時に使うと… Polynomial p; … スレッド2 auto valsGivingZero = p.roots(); スレッド1 auto rootsOfP = p.roots(); const メンバ関数だから読むだけだし、 同期しなくても大丈夫っしょ!! 死
14.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1
15.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false
16.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ②rootsAreValid を読む ⇓ まだ false!
17.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false!
18.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false! ④計算しては書き込む! (まだ false)
19.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false! ④計算しては書き込む! (まだ false) データレース!
20.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { if (!rootsAreValid) { … rootsAreValid = true; } return rootVals; } private: mutable bool rootsAreValid{ false }; mutable RootsType rootVals{}; }; スレッド2スレッド1 ①rootsAreValid を読む ⇓ まだ false ③計算しては書き込む! (まだ false) ②rootsAreValid を読む ⇓ まだ false! ④計算しては書き込む! (まだ false) データレース!ようこそUBへ!
21.
Item 16: Make
const member functions thread safe. ここでの問題は… roots は const メンバ関数なのに、スレッドセーフじゃない。 ⇓ const メンバ関数であることは C++11 でも C++98 でも正しい。 (rootsは多項式の値を変更しない) ⇓ 直すべきはスレッドセーフ性の欠如
22.
Item 16: Make
const member functions thread safe. 解決策 mutex を使え
23.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { std::lock_guard<std::mutex> g(m); ここは前と一緒… return rootVals; } private: mutable std::mutex m; ここも前と一緒… }; lock_guard を使って m をロック! ブロックの終わりで m をアンロック! ここの mutable にも注意! ロック、アンロックは const メンバ関数じゃない でも、m が変わっても多項式はやっぱり変わらない!
24.
Item 16: Make
const member functions thread safe. Caution!(Errataあり) std::mutex はコピーもムーブもできない。 Polynomial に m を追加した結果、 コピーもムーブも出来なくなった。
25.
Item 16: Make
const member functions thread safe. Caution!(Errataあり) std::mutex はコピーもムーブもできない。 Polynomial に m を追加した結果、 コピーもムーブも出来なくなった。 独自のコピー、ムーブコンストラ クタ、代入演算子を定義すれば いいと思うんだけど…
26.
Item 16: Make
const member functions thread safe. コメントあり もし Polynomial が変更不可だったら、std::call_once と std::once_flag を使う方がいんじゃね? ⇓ ちょっと書いてみました
27.
Item 16: Make
const member functions thread safe. class Polynomial { public: using RootsType = std::vector<double>; RootsType roots() const { std::call_once(flag, [this]{ calc(); }); return rootVals; } void calc() const { … } private: mutable std::once_flag flag{}; mutable RootsType rootVals{}; }; call_once を使って calc を一回だけ呼ぶ (λ をつかってる理由は Item 34 参照) 実際に計算、格納するメンバ関数 もちろん const メンバ関数 もちろん once_flag も mutable!
28.
Item 16: Make
const member functions thread safe. 場合によっては mutex は重過ぎ 例)メンバ関数が呼ばれた回数を数えたい ⇓ std::atomic で十分 (実際に std::atomic の方が mutex より軽いかどうかは、 動作するハードウェアと標準ライブラリの実装によるので注意!)
29.
Item 16: Make
const member functions thread safe. class Point { public: … double distanceFromOrigin() const noexcept { ++callCount; return std::hypot(x, y); } private: mutable std::atomic<unsigned> callCount{ 0 }; double x, y; }; アトミック(不可分)なインクリメント (Item 40 参照)
30.
Item 16: Make
const member functions thread safe. class Point { public: … double distanceFromOrigin() const noexcept { ++callCount; return std::hypot(x, y); } private: mutable std::atomic<unsigned> callCount{ 0 }; double x, y; }; 例によって、std::atomic<T> も コピーはおろかムーブも 出来ないので注意! (本書Errata)
31.
Item 16: Make
const member functions thread safe. class Point { // 二次元の点 public: … double distanceFromOrigin() const noexcept // noexcept については { ++callCount; return std::hypot(x, y); } private: mutable std::atomic<unsigned> callCount{ 0 }; double x, y; }; あ、あと、std::hypotも わりとデキる奴なので 忘れないであげてください!(><) (本書Errata) hypotenuse squared
32.
Item 16: Make
const member functions thread safe. でも… mutex より std::atomic の方が軽いからと言って、 使いすぎは禁物! 例)重い計算結果のキャッシュ(int)と キャッシュの有効フラグ(bool)
33.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; キャッシュする値と その有効フラグを atomic にしました!
34.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; キャッシュする値と その有効フラグを atomic にしました! ホントに 大丈夫…?
35.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1
36.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ①有効か確認する ⇓ まだ無効
37.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ①有効か確認する ⇓ まだ無効
38.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効
39.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④計算して格納 (まだ無効)
40.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } private: mutable std::atomic<bool> cacheValid{ false }; mutable std::atomic<int> cachedValue; }; スレッド2スレッド1 ②計算して格納 (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④計算して格納 (まだ無効)残念!!!
41.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; じゃあじゃあ、 キャッシュの有効化と 値の代入を逆にしよう!
42.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; じゃあじゃあ、 キャッシュの有効化と 値の代入を逆にしよう! ホントにホントに 大丈夫…?
43.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1
44.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ①有効か確認する ⇓ まだ無効
45.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ①有効か確認する ⇓ まだ無効
46.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効
47.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④2つとも計算する (まだ無効)
48.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効か確認する ⇓ まだ無効 ①有効か確認する ⇓ まだ無効 ④2つとも計算する (まだ無効) 残念!!! (本書Errata)
49.
Item 16: Make
const member functions thread safe. でも… 実はもっとヤバい…
50.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1
51.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ①有効か確認する ⇓ まだ無効
52.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ①有効か確認する ⇓ まだ無効
53.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効にする! (まだ格納前!) ①有効か確認する ⇓ まだ無効
54.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効にする! (まだ格納前!) ④有効か確認する ⇓ 有効!? 値を返す!!! ①有効か確認する ⇓ まだ無効
55.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cacheValid = true; return cachedValue = val1 + val2; } } … }; スレッド2スレッド1 ②2つとも計算する (まだ無効) ③有効にする! (まだ格納前!) ④有効か確認する ⇓ 有効!? 値を返す!!! ①有効か確認する ⇓ まだ無効 死
56.
Item 16: Make
const member functions thread safe. 教訓 単一の変数やメモリ位置の同期が必要 ⇒ std::atomic 2 つ以上の変数やメモリ位置に対して不可分操作が必要 ⇒ mutex(std::atomic じゃNG!)
57.
Item 16: Make
const member functions thread safe. class Widget { public: … int magicValue() const { std::lock_guard<std::mutex> guard(m); if (cacheValid) return cachedValue; else { auto val1 = expensiveComputation1(); auto val2 = expensiveComputation2(); cachedValue = val1 + val2; cacheValid = true; return cachedValue; } } … private: mutable std::mutex m; mutable int cachedValue; mutable bool cacheValid{ false }; }; lock_guard を使って m をロック! ブロックの終わりで m をアンロック! 例によって mutable! もはや atomic の必要なし!
58.
Item 16: Make
const member functions thread safe. ところで… 散々マルチスレッドの話をしてきたけど、 シングルスレッド前提の場合は? ⇓ これらの対応は不要 (その場合、mutex や std::atomic に 関するコストを避けられる)
59.
Item 16: Make
const member functions thread safe. ところで… 散々マルチスレッドの話をしてきたけど、 シングルスレッド前提の場合は? ⇓ これらの対応は不要 (その場合、mutex や std::atomic に 関するコストを避けられる)
60.
Item 16: Make
const member functions thread safe. え ー マ ジ マ ル チ ス レ ッ ド 未 対 応 ⁉ マ ル チ ス レ ッ ド 未 対 応 が 許 さ れ る の は 小 学 生 ま で だ よ ね ー ©キモイガールズ
61.
Item 16: Make
const member functions thread safe. 覚えておくこと • 並行コンテキストで決して使用しないと確信できない限り、 const メンバ関数をスレッドセーフにしておくこと。 • std::atomic の使用は mutex よりも良いパフォーマンスを示す かもしれないが、それは単一の変数やメモリ位置への操作のみに適 している。
Download