SlideShare una empresa de Scribd logo
1 de 51
Concurrent 同期入門
株式会社ピクセラ
製品事業本部
ソフトウェア開発部門
先端技術開発部
© 2017 PIXELA CORPORATION|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
2019年6月21日
発表の目的
○ マルチスレッドプログラミングにおける競合について知ってもらう
○ 同期オブジェクトについて知ってもらう
○ マルチスレッド設計/実装のノウハウを知ってもらう
2Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
アジェンダ
○ 1: マルチスレッドクイズ
○ 2: 競合とその原因と対策
○ 3: 同期オブジェクト
○ 4: 設計/実装上の注意
○ 5: Atomic 変数操作
3Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
1:マルチスレッドクイズ
4Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
このコードの x がとりうる値は?
5
int x = 0;
void func1() {
for (int i = 0; i < 1000000; i++) x++;
}
int main()
{
std::thread t1([]() { func1(); }), t2([]() { func1(); });
t1.join(); t2.join();
printf("x:%dn", x);
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
2:競合とその原因と対策
6Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
競合 (1) : データ競合 (data race)
○ 複数スレッドで同じ変数に対して同時に Read/Write が発生する
○ 厳密には少なくとも一つが Write となる
○ 発生現象
○ 何が発生するか予想できない
○変更途中の値が Read (変数がレジスタ幅を超える場合)
○Write 順が他のスレッドの Read に反映されない
○ 原因
○コードと CPU 命令の乖離
○CPU の内部動作 (キャッシュ)
7Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
競合 (1) : データ競合 (data race)
8
int my_account = 0; // 私の預金口座残高
int your_account = 100; // あなたの預金口座残高
// 送金処理
bool racy_transfer(int m) {
if (m <= my_account) { // 未定義動作の可能性あり!
my_account -= m; // 未定義動作の可能性あり!
your_account += m; // 未定義動作の可能性あり!
return true;
}
return false;
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
競合 (2) : 競合状態 (race condition)
○ 実行タイミングに依存してシステムの出力結果が変化する
○ 発生現象
○ 変数が不変条件に違反した値になる
○ タイミングによって不具合発生、sleep を入れるとクラッシュ
○ 原因
○ 設計/実装ミス
○複数のリソースに対する操作が排他されていない
○スレッド間の調停を行っていない
9Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
競合 (2) : 競合状態 (race condition)
10
std::atomic<int> my_account = 0; // 私の預金口座残高
std::atomic<int> your_account = 100; // あなたの預金口座残高
// 送金処理
bool unsafe_transfer(int m)
{
if (m <= my_account) {
// ★この時点でも(m <= my_account)は真?
my_account -= m;
your_account += m;
return true;
}
return false;
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
競合への対策 (基本)
○ 操作を不可分 (atomic) とする
○ atomic とは一連の操作が他スレッドから一体と見えること
○全操作が完了するまで他スレッドから変更が見えない
○操作失敗時には操作前の状態に戻る
○複数スレッドで同時に操作できない
○ 例: 複数スレッドからアクセスされるリソースを排他する
○ 前提条件を満たしてから実行する
○ 他のスレッドの入力を待つような場合
11Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
正しいコード
12
int my_account = 0; // 私の預金口座残高
int your_account = 100; // あなたの預金口座残高
std::mutex txn_guard;
// 送金処理: 安全なトランザクション処理
bool safe_transfer(int m)
{
std::lock_guard<std::mutex> lk(txn_guard);
if (m <= my_account) {
my_account -= m;
your_account += m;
return true;
}
return false;
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
3:同期オブジェクト
13Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
代表的な同期オブジェクト
○ Mutex
○ Read-Write Lock
○ Condition Variable
○ Event
○ Semaphore
○ Volatile (正確には同期オブジェクトではない)
14Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Mutex
○ ロックすることでそれ以降のコードへのアクセス権を取得する
○ 同時にロックできるのは一つのスレッドのみ
○ 同じ Mutex をロックしているコード間は排他されている
○ Mutex の作り方によって同じスレッドが複数回ロックをとれる (Recursive) なもの
とできないものがある
○ パフォーマンスが要求されない限り Recursive にするのが安全
○後の修正で Recursive が必要になるかもという理由
15Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Mutex コード例 (C++)
16
int func()
{
static std::recursive_mutex mutex;
std::lock_guard<std::recursive_mutex>
lock(mutex);
static int count = 0;
count++;
return count;
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Read-Write Lock
○ Read は複数あっても race condition は起きないことを利用してパフォーマンス向
上を行う
○ Read のロック API と Write API のロックが分かれている
○ Read だけなら複数取得可
○ Write と Read, 複数の Write は同時に行えない
○ Write に比べて Read が多い場合にロック待ち時間を削減できる
17Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Read-Write Lock コード例 (Win32 API)
18
void init(SRWLOCK* lock) {
InitializeSRWLock(lock);
}
static int count = 0;
int read(SRWLOCK* lock) {
// AcquireSRWLockExclusive がない限り通る
AcquireSRWLockShared(lock);
int ret = count;
ReleaseSRWLockShared(lock);
return ret;
}
int write(int val, SRWLOCK* lock) {
// 他の AcquireSRWLockExclusive, AcquireSRWLockShared がない限り通る
AcquireSRWLockExclusive(lock);
count = val;
ReleaseSRWLockExclusive(lock);
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Condition Variable
○ 待機側が待機し、通知側が待機側を起動させる
○ 待機側が待機前にロックオブジェクト (Mutex, Read-Write Lock) を握っているの
が前提となる
○ 待機と不可分に行える
○ “条件変数” とよばれているのは以下のような使われ方のため
○ 待機側は処理条件を満たしていない場合に待機する
○ 通知側は待機側の処理条件を満たした状態にして通知する
19Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Condition Variable コード例 (C++)
20
static std::mutex mutex;
static std::condition_variable cond;
bool flag = false;
void wait() {
// flag が true になるまで待機。
std::unique_lock<std::mutex> lock(mutex);
cond.wait(lock, []() { return flag; });
flag = false;
}
void wake() {
// 待機スレッドを起こす
{ std::unique_lock<std::mutex> lock(mutex); flag = true; }
cond.notify_one();
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Event
○ 通知側が通知を行うと待機しているスレッドが起動する
○ オブジェクトの Signal (通ってよし) と Non-Signal (通行止め) を管理する
○ Signal 状態でロックとると non-Signal になる/ならないとか、初期状態セットでき
るとかバリエーションがいっぱいある
○ ので使う際には OS のリファレンスをちゃんと読む必要がある
○ 典型的な例は I/O 待ち
21Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Event コード例 (Win32 API)
22
int init(HANDLE *handle) {
// 自動で non-signal になる初期値 non-signal のイベント作成
*handle = CreateEvent(/*atrtributes*/NULL,/*manual_reset*/FALSE,
/*initial_state*/FALSE, /*name*/NULL );
}
void wait(HANDLE handle) {
// signal 状態まで待つ
// 自動で non-signal になるので一度に起動するスレッドはひとつ
WaitForSingleObject(handle, INFINITE);
}
void wake(HANDLE handle) {
SetEvent(handle);
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Semaphore
○ 指定回数だけ取得できる
○ 解放は取得者でなくてもよい
○ リソースの共有数の管理に使えるはず
○ Mutex と条件変数でも実装できるが…
23Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Semaphore コード例 (Win32 API)
24
int func()
{
static HANDLE sem = CreateSemaphore(
/*attributes*/NULL, /*initial count*/5, /*max count*/ 12, /*name*/ NULL
);
WaitForSingleObject(sem, INFINITE); // count--, count > 0 でロックされない
// 処理
// count 増加 -> 待機スレッド起動
ReleaseSemaphore(sem, /*count*/1, /*[out] prev_count*/NULL);
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Volatile
○ コンパイラによる最適化を防ぐ
○ 変数アクセス時に逐次メモリを読みに行く
○ループ中のスレッド外部での変数の変更の検出に使える
○ 関数内での命令リオーダーは防げない
○コードの記述順に Read/Write されると期待すべきではな
い
○ Volatile ではなく適切な atomic 機構に頼るべき
○ Volatile を使うケースは以下
○ 外部ハードウェアデバイスを参照している場合
25Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Volatile コード例 (C++)
26
// デバイス側で変更されるフラグ
extern volatile int flag;
int wait() {
// busy-loop でチェック
// 外部で flag が true になれば抜ける
while (!flag) {};
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
注意点
○ 各同期オブジェクトが使用できる/できないは OS や言語によって違う
○ 各同期オブジェクトがプロセス間で共有できる/できないは OS 依存
○ C++ の各オブジェクト操作が OS のどの API に相当するかは stdlib の実装依存となっ
ている
○ パフォーマンスが必要なら軽い API に切り替える必要がある
○ スペースの都合上ヘッダの include は省略した
○ 共有オブジェクトが static 変数になっているのはスペースの都合上なので実装ではやら
ないこと
27Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
4:設計/実装上の注意
28Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
生のロックオブジェクトは扱わない
○ ロックオブジェクトを操作するコードを直接書かない
○ アンロックするコードをロック区間出口の数だけ書く必要性
○ C++ なら std::lock_guard 等を使う
○ RAII (Resource Acquisition Is Initialization)
○ スタック上にのったオブジェクトの破棄時にリソース破棄が発生
○ C の場合 RAII は使えないので goto パターンでアンロックを一か所に集めること
29Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
条件変数の spurious wakeup
○ 条件変数での待機処理にて通知なしでブロック解除される現象
○ 原因はライブラリ内部処理やハードウェア/OS の都合
○ 発生頻度はごく低い…はず
○ 対応 : 条件変数を使う場合は必ず待機終了後に待機条件をチェック
○ 満たしていない場合は再度待機
30Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
デッドロックを防ぐために – 原因
○ デッドロックは 2 個以上のロックの取得順番が違うときに発生する
○ 特に危ないケース
○ ロックを取得したまま他モジュールを呼びに行き、そのモジュールから自モ
ジュールを呼び出す経路がある場合
○同じスレッドでの呼び出しは問題ないが、異なるスレッドで
の呼び出し経路があると最悪
○ モジュール内に複数ロックオブジェクトがある場合
○常にロック順序を一定にする必要がある
31Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
デッドロックを防ぐために – 状況
32Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
デッドロックを防ぐために – 対策
○ 排他区間を短くする
○ モジュール内のロックオブジェクトを一つにする
○ モジュール相互の呼び出しが発生するパスを作らない
○ ロックを取得したまま他モジュールを呼ばない
○ 上位モジュールの処理は上位モジュールのスレッドで処理する
○ いったん上位モジュールのタスクキューで受ける等
○タスクキューが詰まってデッドロックになる場合も (実例)
○ 下位モジュールのロックを処理から切り離す
33Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Sleep 時間はベストエフォート
○ 各種 sleep/待機関数に渡す時間はその時間での起動を保証しない
○ スレッドスケジューリング (スレッド優先度等) の都合上起動が待たされる可能性が
ある
○ また、起動の精度はタイマー割り込みの頻度に依存する
○ Windows: 16 millisecond (デフォルト状態)
○ PC Linux: 4 millisecond (2010 の情報)
34Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
精密な Sleep 時間が必要な場合
○ 精密に起動できるようにする
○ タイマー割り込み頻度の変更 (1 msec 精度まで)
○ スレッド優先度の引き上げ
○ Busy loop の採用
35Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
5:Atomic 変数操作
36Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
ロックによるオーバヘッド
○ 頻繁にアクセスする変数にロックをかけるとパフォーマンス低下
○ 頻繁な状態チェック
○ API 呼び出し -> カーネル空間への移動
○ メモリを Atomic に操作する変数 (正確にはメモリを Atomic に操作する CPU 命
令) を使えばパフォーマンスが向上する
37Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Atomic 変数の前に – data race の原因
○ コードと CPU 命令の乖離
○ CPU 内部の都合
○ キャッシュの同期が基本行われない
38Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Data race : コードと CPU 命令の乖離 (1)
○ 下の処理中でコンテキストスイッチとなった場合、
再開時は昔のメモリを読み込んだ状態で処理再開
される
39
int func(int *ptr) {
*ptr++;
}
int func(int *ptr) {
int val = *ptr;
val++;
*ptr = val;
}
おおよそ
次のように展開される
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Data race : コードと CPU 命令の乖離 (2)
○ 変数がレジスタ幅に収まらない場合、メモリ書き込
み途中で他スレッドから読み取られる可能性がある
○ 矛盾した状態を読み込んでしまう
40
struct St {
int64_t a;
int64_t b;
};
int set(St *ptr) {
*ptr = { 123, 125 };
}
おおよそ
次のように展開される
struct St {
int64_t a;
int64_t b;
};
int set(St *ptr) {
ptr->a = 123;
ptr->b = 125;
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Data race : CPU キャッシュ (1)
41
メインメモリ (DRAM)
L3 キャッシュ
L1 キャッシュ
L2 キャッシュL2 キャッシュ
L1 キャッシュ
Core 1 Core 2
○ メモリアクセスは遅いのでキャッ
シュ階層を設ける
○ 容量と速度の要請から複数段に分か
れている
○ Core に近いキャッシュは Core ごと
に用意されている
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Data race : CPU キャッシュ (2)
42
メインメモリ (DRAM)
L3 キャッシュ
L1 キャッシュ
L2 キャッシュL2 キャッシュ
L1 キャッシュ
Core 1 Core 2
○ ある Core でのメモリ書き込みが他
の Core に見えるまでには時間がか
かる
○ 左図では最速 44 clock 先
○ 異なる Core で同じアドレスを読み
込んでいた場合、自分のキャッシュ
にある値を読み込み書き込みに気が
付かない4 clocks
11 clocks
22 clocks
たくさん
レイテンシ
write
時間をかけて伝わる
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
CPU に必要な機能
○ メモリを直接操作する
○ ある Core での操作が他の Core にすぐ見える
○ キャッシュの整合性を保つ
○他の Core をストールさせる
○キャッシュ間の同期をとる
43Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Intel X86 CPU 命令
○ LOCK XADD [mem] r
○ r = [mem], [mem] = [mem] + r
○ LOCK CMPXCHG [mem] r eax
○ if (eax == [mem]) { [mem] = r } else { eax = [mem] }
○ これらの命令を使うことで core 間の同期をとりつつ処理できる
44Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
C++ atomic 変数
○ Atomic CPU 命令をラップしてくれるクラス
○ 変数への操作を適切な atomic CPU 命令に変換してくれる
○ アーキテクチャによって提供されるビット幅等が違う
45
std::atomic<int> val = 128;
void func() {
int chk = 256;
val.compare_exchange_weak(chk, 1024); // lock cmpxchg
val++; // lock xadd
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
C++ atomic 変数
○ 利点 : data race を除去できる
○ 欠点 : ある程度のオーバーヘッドがある
○ 常にメモリ上に変数が配置されるうえに Cache の整合性を保つ処理が入る
○同じキャッシュラインへの操作はストールする
○ 使い方
○ #include <atomic> する
○ atomic にしたい変数を std::atomic<type> とする
○アーキテクチャによって type に入れれる型は違う
46Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
応用 :lock-free アルゴリズム
○ Compare and Swap (CAS) を利用して読み取り値が変わらない場合のみ操作成功
させる
○ Intel CPU の命令は CMPXCHG だが一般的な用語は Compare and Swap
○ 操作中に割り込みが入った場合 CAS が成功しないので (事前に読み取った値と異な
る値が返される) 成功するまでリトライを繰り返す
47Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Lock – free アルゴリズム例
○ 現在値が引く値よりも大きければ引く操作
○ Compare and exchange に成功すれば ret には tmp が入るはず
○ (ret == tmp) で成功判定できる
48
std::atomic<int> val = 128;
void minus(int sub) {
int tmp = 0; int ret = 0;
do {
ret = tmp = val;
if (sub <= tmp) {
ret = val.compare_exchange_weak(tmp, tmp - sub);
}
} while (ret != tmp);
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
応用 : SpinLock
○ Mutex と機能は同じだがビジーウェイトによってロック解放を待つ
○ ロック対象処理が短い場合に Mutex よりも反応性がよい
○ シングルコア CPU では意味がない
○ 実装は atomic 変数の操作で行う
49Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
SpinLock 実装
50
class spinlock {
private:
std::atomic_flag state_;
public:
spinlock() : state_(ATOMIC_FLAG_INIT) {}
void lock() {
// busy-wait で現在の状態をロック状態にする
while (state_.test_and_set(std::memory_order_acquire));
}
void unlock() {
state_.clear(std::memory_order_release); // 値をアンロック状態にする
}
};
int func() {
static spinlock lock;
std::lock_guard<spinlock> lk(lock);
static int val = 0; return val++;
}
Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
Introduction to conccrent_lock

Más contenido relacionado

La actualidad más candente

Mk vpp for-containers-vppug
Mk vpp for-containers-vppugMk vpp for-containers-vppug
Mk vpp for-containers-vppugMiya Kohno
 
Hyperledger Fabric のプラットフォームおよびインフラ運用
Hyperledger Fabric のプラットフォームおよびインフラ運用Hyperledger Fabric のプラットフォームおよびインフラ運用
Hyperledger Fabric のプラットフォームおよびインフラ運用Hyperleger Tokyo Meetup
 
Mk onic data-intensive-public
Mk onic data-intensive-publicMk onic data-intensive-public
Mk onic data-intensive-publicMiya Kohno
 
ニフティクラウドでのVyOS利用事例
ニフティクラウドでのVyOS利用事例ニフティクラウドでのVyOS利用事例
ニフティクラウドでのVyOS利用事例Shintaro Hasunuma
 
20181129 Twilio Business Seminar in Osaka #2
20181129 Twilio Business Seminar  in Osaka #220181129 Twilio Business Seminar  in Osaka #2
20181129 Twilio Business Seminar in Osaka #2Ukyo Satake
 
デバイスWebAPIによるIoTの普及拡大と応用事例
デバイスWebAPIによるIoTの普及拡大と応用事例デバイスWebAPIによるIoTの普及拡大と応用事例
デバイスWebAPIによるIoTの普及拡大と応用事例Device WebAPI Consortium
 
BGP as a method for Abstraction
BGP as a method for AbstractionBGP as a method for Abstraction
BGP as a method for AbstractionMiya Kohno
 
SORACOMでのJava/AWS活用
SORACOMでのJava/AWS活用SORACOMでのJava/AWS活用
SORACOMでのJava/AWS活用Akio Katayama
 
Intellectual Highway/貞末様 講演資料
Intellectual Highway/貞末様 講演資料Intellectual Highway/貞末様 講演資料
Intellectual Highway/貞末様 講演資料直久 住川
 

La actualidad más candente (19)

マスタリングTCP/IP ニフクラ編
マスタリングTCP/IP ニフクラ編マスタリングTCP/IP ニフクラ編
マスタリングTCP/IP ニフクラ編
 
NIFcLab Tech Laboratoryはじめます(もうすぐ)
NIFcLab Tech Laboratoryはじめます(もうすぐ)NIFcLab Tech Laboratoryはじめます(もうすぐ)
NIFcLab Tech Laboratoryはじめます(もうすぐ)
 
ニフクラ mobile backend チームのCIツール活用事例紹介
ニフクラ mobile backend チームのCIツール活用事例紹介ニフクラ mobile backend チームのCIツール活用事例紹介
ニフクラ mobile backend チームのCIツール活用事例紹介
 
vm meetup_tokyo #1 NSX の運用と DFW トラブルシューティング
vm meetup_tokyo #1 NSX の運用と DFW トラブルシューティングvm meetup_tokyo #1 NSX の運用と DFW トラブルシューティング
vm meetup_tokyo #1 NSX の運用と DFW トラブルシューティング
 
これから始めるエンジニアのためのクラウド超入門
これから始めるエンジニアのためのクラウド超入門これから始めるエンジニアのためのクラウド超入門
これから始めるエンジニアのためのクラウド超入門
 
Mk vpp for-containers-vppug
Mk vpp for-containers-vppugMk vpp for-containers-vppug
Mk vpp for-containers-vppug
 
Hyperledger Fabric のプラットフォームおよびインフラ運用
Hyperledger Fabric のプラットフォームおよびインフラ運用Hyperledger Fabric のプラットフォームおよびインフラ運用
Hyperledger Fabric のプラットフォームおよびインフラ運用
 
クラウド上のシステム監視 入門編~システムを作ったその先に~
クラウド上のシステム監視 入門編~システムを作ったその先に~クラウド上のシステム監視 入門編~システムを作ったその先に~
クラウド上のシステム監視 入門編~システムを作ったその先に~
 
devsummit_nifcloud_vmware
devsummit_nifcloud_vmwaredevsummit_nifcloud_vmware
devsummit_nifcloud_vmware
 
Mk onic data-intensive-public
Mk onic data-intensive-publicMk onic data-intensive-public
Mk onic data-intensive-public
 
ニフティクラウドでのVyOS利用事例
ニフティクラウドでのVyOS利用事例ニフティクラウドでのVyOS利用事例
ニフティクラウドでのVyOS利用事例
 
2016-ShowNet-対外接続(エクスターナル)
2016-ShowNet-対外接続(エクスターナル)2016-ShowNet-対外接続(エクスターナル)
2016-ShowNet-対外接続(エクスターナル)
 
20181129 Twilio Business Seminar in Osaka #2
20181129 Twilio Business Seminar  in Osaka #220181129 Twilio Business Seminar  in Osaka #2
20181129 Twilio Business Seminar in Osaka #2
 
デバイスWebAPIによるIoTの普及拡大と応用事例
デバイスWebAPIによるIoTの普及拡大と応用事例デバイスWebAPIによるIoTの普及拡大と応用事例
デバイスWebAPIによるIoTの普及拡大と応用事例
 
2015-ShowNet-報告資料
2015-ShowNet-報告資料2015-ShowNet-報告資料
2015-ShowNet-報告資料
 
BGP as a method for Abstraction
BGP as a method for AbstractionBGP as a method for Abstraction
BGP as a method for Abstraction
 
SORACOMでのJava/AWS活用
SORACOMでのJava/AWS活用SORACOMでのJava/AWS活用
SORACOMでのJava/AWS活用
 
Intellectual Highway/貞末様 講演資料
Intellectual Highway/貞末様 講演資料Intellectual Highway/貞末様 講演資料
Intellectual Highway/貞末様 講演資料
 
nifcloud_meetup
nifcloud_meetupnifcloud_meetup
nifcloud_meetup
 

Similar a Introduction to conccrent_lock

Springのプログラムモデルと動く仕様~テスト編~
Springのプログラムモデルと動く仕様~テスト編~Springのプログラムモデルと動く仕様~テスト編~
Springのプログラムモデルと動く仕様~テスト編~terahide
 
OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料
OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料
OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料オラクルエンジニア通信
 
Network Programmability and the statefulness/transactionality
Network Programmability and the statefulness/transactionalityNetwork Programmability and the statefulness/transactionality
Network Programmability and the statefulness/transactionalityMiya Kohno
 
Mk state in-programming-01
Mk state in-programming-01Mk state in-programming-01
Mk state in-programming-01Miya Kohno
 
Spring I/O 2018 報告 RESTDocs RAML, Cloud Contract
Spring I/O 2018 報告 RESTDocs RAML, Cloud ContractSpring I/O 2018 報告 RESTDocs RAML, Cloud Contract
Spring I/O 2018 報告 RESTDocs RAML, Cloud ContractTakuya Iwatsuka
 
オープンソースライセンス ケーススタディ
オープンソースライセンス ケーススタディオープンソースライセンス ケーススタディ
オープンソースライセンス ケーススタディYutaka Kachi
 
Hyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオン
Hyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオンHyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオン
Hyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオン健一 茂木
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„和弘 井之上
 
20200122 なぜ企業はブロックチェーン応用に取り組むのか
20200122 なぜ企業はブロックチェーン応用に取り組むのか20200122 なぜ企業はブロックチェーン応用に取り組むのか
20200122 なぜ企業はブロックチェーン応用に取り組むのかオラクルエンジニア通信
 
【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する
【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する
【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化するLIFULL Co., Ltd.
 
20190825_MySQL ServerだけじゃないMySQL Shellもあるんです
20190825_MySQL ServerだけじゃないMySQL Shellもあるんです20190825_MySQL ServerだけじゃないMySQL Shellもあるんです
20190825_MySQL ServerだけじゃないMySQL ShellもあるんですMachiko Ikoma
 
クラウドを最大限活用するinfrastructure as codeを考えよう
クラウドを最大限活用するinfrastructure as codeを考えようクラウドを最大限活用するinfrastructure as codeを考えよう
クラウドを最大限活用するinfrastructure as codeを考えようNTT Communications Technology Development
 
OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向
OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向
OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向Midokura
 
AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)
AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)
AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)AzareaCluster
 
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)NTT DATA OSS Professional Services
 
JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...
JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...
JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...David Buck
 
TypeScript製フレームワーク「Nest」のご紹介
TypeScript製フレームワーク「Nest」のご紹介TypeScript製フレームワーク「Nest」のご紹介
TypeScript製フレームワーク「Nest」のご紹介bitbank, Inc. Tokyo, Japan
 

Similar a Introduction to conccrent_lock (20)

Springのプログラムモデルと動く仕様~テスト編~
Springのプログラムモデルと動く仕様~テスト編~Springのプログラムモデルと動く仕様~テスト編~
Springのプログラムモデルと動く仕様~テスト編~
 
20181228 ncf to_azure_batch
20181228 ncf to_azure_batch20181228 ncf to_azure_batch
20181228 ncf to_azure_batch
 
OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料
OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料
OCHaCafe #4 Hyperledger Fabric アプリケーション設計入門ガイドでしゃべった内容+おまけ資料
 
Network Programmability and the statefulness/transactionality
Network Programmability and the statefulness/transactionalityNetwork Programmability and the statefulness/transactionality
Network Programmability and the statefulness/transactionality
 
Mk state in-programming-01
Mk state in-programming-01Mk state in-programming-01
Mk state in-programming-01
 
Spring I/O 2018 報告会
Spring I/O 2018 報告会Spring I/O 2018 報告会
Spring I/O 2018 報告会
 
Spring I/O 2018 報告 RESTDocs RAML, Cloud Contract
Spring I/O 2018 報告 RESTDocs RAML, Cloud ContractSpring I/O 2018 報告 RESTDocs RAML, Cloud Contract
Spring I/O 2018 報告 RESTDocs RAML, Cloud Contract
 
オープンソースライセンス ケーススタディ
オープンソースライセンス ケーススタディオープンソースライセンス ケーススタディ
オープンソースライセンス ケーススタディ
 
Hyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオン
Hyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオンHyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオン
Hyperledgerのチュートリアルで理解する基幹システム向けブロックチェーンハンズオン
 
Spring I/O 2015 報告
Spring I/O 2015 報告Spring I/O 2015 報告
Spring I/O 2015 報告
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第5回 ‟配列と構造体„
 
20200122 なぜ企業はブロックチェーン応用に取り組むのか
20200122 なぜ企業はブロックチェーン応用に取り組むのか20200122 なぜ企業はブロックチェーン応用に取り組むのか
20200122 なぜ企業はブロックチェーン応用に取り組むのか
 
【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する
【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する
【Ltech#10】LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化する
 
20190825_MySQL ServerだけじゃないMySQL Shellもあるんです
20190825_MySQL ServerだけじゃないMySQL Shellもあるんです20190825_MySQL ServerだけじゃないMySQL Shellもあるんです
20190825_MySQL ServerだけじゃないMySQL Shellもあるんです
 
クラウドを最大限活用するinfrastructure as codeを考えよう
クラウドを最大限活用するinfrastructure as codeを考えようクラウドを最大限活用するinfrastructure as codeを考えよう
クラウドを最大限活用するinfrastructure as codeを考えよう
 
OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向
OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向
OpenStack Networkingとネットワーク仮想化ソフトMidoNet最新動向
 
AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)
AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)
AZAREA-Cluster (Hadoop Conference Japan 2013 Winter)
 
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
 
JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...
JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...
JDK Mission Control: Where We Are, Where We Are Going [Groundbreakers APAC 20...
 
TypeScript製フレームワーク「Nest」のご紹介
TypeScript製フレームワーク「Nest」のご紹介TypeScript製フレームワーク「Nest」のご紹介
TypeScript製フレームワーク「Nest」のご紹介
 

Más de PIXELAcorporation

Más de PIXELAcorporation (10)

Introduction to Functional Programming
Introduction to Functional ProgrammingIntroduction to Functional Programming
Introduction to Functional Programming
 
20190620 aws summit_tokyo_2019
20190620 aws summit_tokyo_201920190620 aws summit_tokyo_2019
20190620 aws summit_tokyo_2019
 
Global Azure Boot Camp 2019
Global Azure Boot Camp 2019Global Azure Boot Camp 2019
Global Azure Boot Camp 2019
 
IP接続性の向上
IP接続性の向上IP接続性の向上
IP接続性の向上
 
What is ocf ?
What is ocf ?What is ocf ?
What is ocf ?
 
エッジAI入門
エッジAI入門エッジAI入門
エッジAI入門
 
PIXELA passport ID
PIXELA passport IDPIXELA passport ID
PIXELA passport ID
 
4K SmartTV Works with Alexa
4K SmartTV Works with Alexa4K SmartTV Works with Alexa
4K SmartTV Works with Alexa
 
Face seek ai edge
Face seek ai edgeFace seek ai edge
Face seek ai edge
 
TVCM視聴分析
TVCM視聴分析TVCM視聴分析
TVCM視聴分析
 

Último

Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイスCRI Japan, Inc.
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルCRI Japan, Inc.
 

Último (7)

Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

Introduction to conccrent_lock

  • 1. Concurrent 同期入門 株式会社ピクセラ 製品事業本部 ソフトウェア開発部門 先端技術開発部 © 2017 PIXELA CORPORATION|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL. 2019年6月21日
  • 2. 発表の目的 ○ マルチスレッドプログラミングにおける競合について知ってもらう ○ 同期オブジェクトについて知ってもらう ○ マルチスレッド設計/実装のノウハウを知ってもらう 2Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 3. アジェンダ ○ 1: マルチスレッドクイズ ○ 2: 競合とその原因と対策 ○ 3: 同期オブジェクト ○ 4: 設計/実装上の注意 ○ 5: Atomic 変数操作 3Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 4. 1:マルチスレッドクイズ 4Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 5. このコードの x がとりうる値は? 5 int x = 0; void func1() { for (int i = 0; i < 1000000; i++) x++; } int main() { std::thread t1([]() { func1(); }), t2([]() { func1(); }); t1.join(); t2.join(); printf("x:%dn", x); } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 6. 2:競合とその原因と対策 6Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 7. 競合 (1) : データ競合 (data race) ○ 複数スレッドで同じ変数に対して同時に Read/Write が発生する ○ 厳密には少なくとも一つが Write となる ○ 発生現象 ○ 何が発生するか予想できない ○変更途中の値が Read (変数がレジスタ幅を超える場合) ○Write 順が他のスレッドの Read に反映されない ○ 原因 ○コードと CPU 命令の乖離 ○CPU の内部動作 (キャッシュ) 7Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 8. 競合 (1) : データ競合 (data race) 8 int my_account = 0; // 私の預金口座残高 int your_account = 100; // あなたの預金口座残高 // 送金処理 bool racy_transfer(int m) { if (m <= my_account) { // 未定義動作の可能性あり! my_account -= m; // 未定義動作の可能性あり! your_account += m; // 未定義動作の可能性あり! return true; } return false; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 9. 競合 (2) : 競合状態 (race condition) ○ 実行タイミングに依存してシステムの出力結果が変化する ○ 発生現象 ○ 変数が不変条件に違反した値になる ○ タイミングによって不具合発生、sleep を入れるとクラッシュ ○ 原因 ○ 設計/実装ミス ○複数のリソースに対する操作が排他されていない ○スレッド間の調停を行っていない 9Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 10. 競合 (2) : 競合状態 (race condition) 10 std::atomic<int> my_account = 0; // 私の預金口座残高 std::atomic<int> your_account = 100; // あなたの預金口座残高 // 送金処理 bool unsafe_transfer(int m) { if (m <= my_account) { // ★この時点でも(m <= my_account)は真? my_account -= m; your_account += m; return true; } return false; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 11. 競合への対策 (基本) ○ 操作を不可分 (atomic) とする ○ atomic とは一連の操作が他スレッドから一体と見えること ○全操作が完了するまで他スレッドから変更が見えない ○操作失敗時には操作前の状態に戻る ○複数スレッドで同時に操作できない ○ 例: 複数スレッドからアクセスされるリソースを排他する ○ 前提条件を満たしてから実行する ○ 他のスレッドの入力を待つような場合 11Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 12. 正しいコード 12 int my_account = 0; // 私の預金口座残高 int your_account = 100; // あなたの預金口座残高 std::mutex txn_guard; // 送金処理: 安全なトランザクション処理 bool safe_transfer(int m) { std::lock_guard<std::mutex> lk(txn_guard); if (m <= my_account) { my_account -= m; your_account += m; return true; } return false; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 13. 3:同期オブジェクト 13Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 14. 代表的な同期オブジェクト ○ Mutex ○ Read-Write Lock ○ Condition Variable ○ Event ○ Semaphore ○ Volatile (正確には同期オブジェクトではない) 14Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 15. Mutex ○ ロックすることでそれ以降のコードへのアクセス権を取得する ○ 同時にロックできるのは一つのスレッドのみ ○ 同じ Mutex をロックしているコード間は排他されている ○ Mutex の作り方によって同じスレッドが複数回ロックをとれる (Recursive) なもの とできないものがある ○ パフォーマンスが要求されない限り Recursive にするのが安全 ○後の修正で Recursive が必要になるかもという理由 15Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 16. Mutex コード例 (C++) 16 int func() { static std::recursive_mutex mutex; std::lock_guard<std::recursive_mutex> lock(mutex); static int count = 0; count++; return count; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 17. Read-Write Lock ○ Read は複数あっても race condition は起きないことを利用してパフォーマンス向 上を行う ○ Read のロック API と Write API のロックが分かれている ○ Read だけなら複数取得可 ○ Write と Read, 複数の Write は同時に行えない ○ Write に比べて Read が多い場合にロック待ち時間を削減できる 17Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 18. Read-Write Lock コード例 (Win32 API) 18 void init(SRWLOCK* lock) { InitializeSRWLock(lock); } static int count = 0; int read(SRWLOCK* lock) { // AcquireSRWLockExclusive がない限り通る AcquireSRWLockShared(lock); int ret = count; ReleaseSRWLockShared(lock); return ret; } int write(int val, SRWLOCK* lock) { // 他の AcquireSRWLockExclusive, AcquireSRWLockShared がない限り通る AcquireSRWLockExclusive(lock); count = val; ReleaseSRWLockExclusive(lock); } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 19. Condition Variable ○ 待機側が待機し、通知側が待機側を起動させる ○ 待機側が待機前にロックオブジェクト (Mutex, Read-Write Lock) を握っているの が前提となる ○ 待機と不可分に行える ○ “条件変数” とよばれているのは以下のような使われ方のため ○ 待機側は処理条件を満たしていない場合に待機する ○ 通知側は待機側の処理条件を満たした状態にして通知する 19Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 20. Condition Variable コード例 (C++) 20 static std::mutex mutex; static std::condition_variable cond; bool flag = false; void wait() { // flag が true になるまで待機。 std::unique_lock<std::mutex> lock(mutex); cond.wait(lock, []() { return flag; }); flag = false; } void wake() { // 待機スレッドを起こす { std::unique_lock<std::mutex> lock(mutex); flag = true; } cond.notify_one(); } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 21. Event ○ 通知側が通知を行うと待機しているスレッドが起動する ○ オブジェクトの Signal (通ってよし) と Non-Signal (通行止め) を管理する ○ Signal 状態でロックとると non-Signal になる/ならないとか、初期状態セットでき るとかバリエーションがいっぱいある ○ ので使う際には OS のリファレンスをちゃんと読む必要がある ○ 典型的な例は I/O 待ち 21Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 22. Event コード例 (Win32 API) 22 int init(HANDLE *handle) { // 自動で non-signal になる初期値 non-signal のイベント作成 *handle = CreateEvent(/*atrtributes*/NULL,/*manual_reset*/FALSE, /*initial_state*/FALSE, /*name*/NULL ); } void wait(HANDLE handle) { // signal 状態まで待つ // 自動で non-signal になるので一度に起動するスレッドはひとつ WaitForSingleObject(handle, INFINITE); } void wake(HANDLE handle) { SetEvent(handle); } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 23. Semaphore ○ 指定回数だけ取得できる ○ 解放は取得者でなくてもよい ○ リソースの共有数の管理に使えるはず ○ Mutex と条件変数でも実装できるが… 23Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 24. Semaphore コード例 (Win32 API) 24 int func() { static HANDLE sem = CreateSemaphore( /*attributes*/NULL, /*initial count*/5, /*max count*/ 12, /*name*/ NULL ); WaitForSingleObject(sem, INFINITE); // count--, count > 0 でロックされない // 処理 // count 増加 -> 待機スレッド起動 ReleaseSemaphore(sem, /*count*/1, /*[out] prev_count*/NULL); } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 25. Volatile ○ コンパイラによる最適化を防ぐ ○ 変数アクセス時に逐次メモリを読みに行く ○ループ中のスレッド外部での変数の変更の検出に使える ○ 関数内での命令リオーダーは防げない ○コードの記述順に Read/Write されると期待すべきではな い ○ Volatile ではなく適切な atomic 機構に頼るべき ○ Volatile を使うケースは以下 ○ 外部ハードウェアデバイスを参照している場合 25Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 26. Volatile コード例 (C++) 26 // デバイス側で変更されるフラグ extern volatile int flag; int wait() { // busy-loop でチェック // 外部で flag が true になれば抜ける while (!flag) {}; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 27. 注意点 ○ 各同期オブジェクトが使用できる/できないは OS や言語によって違う ○ 各同期オブジェクトがプロセス間で共有できる/できないは OS 依存 ○ C++ の各オブジェクト操作が OS のどの API に相当するかは stdlib の実装依存となっ ている ○ パフォーマンスが必要なら軽い API に切り替える必要がある ○ スペースの都合上ヘッダの include は省略した ○ 共有オブジェクトが static 変数になっているのはスペースの都合上なので実装ではやら ないこと 27Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 28. 4:設計/実装上の注意 28Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 29. 生のロックオブジェクトは扱わない ○ ロックオブジェクトを操作するコードを直接書かない ○ アンロックするコードをロック区間出口の数だけ書く必要性 ○ C++ なら std::lock_guard 等を使う ○ RAII (Resource Acquisition Is Initialization) ○ スタック上にのったオブジェクトの破棄時にリソース破棄が発生 ○ C の場合 RAII は使えないので goto パターンでアンロックを一か所に集めること 29Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 30. 条件変数の spurious wakeup ○ 条件変数での待機処理にて通知なしでブロック解除される現象 ○ 原因はライブラリ内部処理やハードウェア/OS の都合 ○ 発生頻度はごく低い…はず ○ 対応 : 条件変数を使う場合は必ず待機終了後に待機条件をチェック ○ 満たしていない場合は再度待機 30Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 31. デッドロックを防ぐために – 原因 ○ デッドロックは 2 個以上のロックの取得順番が違うときに発生する ○ 特に危ないケース ○ ロックを取得したまま他モジュールを呼びに行き、そのモジュールから自モ ジュールを呼び出す経路がある場合 ○同じスレッドでの呼び出しは問題ないが、異なるスレッドで の呼び出し経路があると最悪 ○ モジュール内に複数ロックオブジェクトがある場合 ○常にロック順序を一定にする必要がある 31Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 32. デッドロックを防ぐために – 状況 32Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 33. デッドロックを防ぐために – 対策 ○ 排他区間を短くする ○ モジュール内のロックオブジェクトを一つにする ○ モジュール相互の呼び出しが発生するパスを作らない ○ ロックを取得したまま他モジュールを呼ばない ○ 上位モジュールの処理は上位モジュールのスレッドで処理する ○ いったん上位モジュールのタスクキューで受ける等 ○タスクキューが詰まってデッドロックになる場合も (実例) ○ 下位モジュールのロックを処理から切り離す 33Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 34. Sleep 時間はベストエフォート ○ 各種 sleep/待機関数に渡す時間はその時間での起動を保証しない ○ スレッドスケジューリング (スレッド優先度等) の都合上起動が待たされる可能性が ある ○ また、起動の精度はタイマー割り込みの頻度に依存する ○ Windows: 16 millisecond (デフォルト状態) ○ PC Linux: 4 millisecond (2010 の情報) 34Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 35. 精密な Sleep 時間が必要な場合 ○ 精密に起動できるようにする ○ タイマー割り込み頻度の変更 (1 msec 精度まで) ○ スレッド優先度の引き上げ ○ Busy loop の採用 35Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 36. 5:Atomic 変数操作 36Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 37. ロックによるオーバヘッド ○ 頻繁にアクセスする変数にロックをかけるとパフォーマンス低下 ○ 頻繁な状態チェック ○ API 呼び出し -> カーネル空間への移動 ○ メモリを Atomic に操作する変数 (正確にはメモリを Atomic に操作する CPU 命 令) を使えばパフォーマンスが向上する 37Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 38. Atomic 変数の前に – data race の原因 ○ コードと CPU 命令の乖離 ○ CPU 内部の都合 ○ キャッシュの同期が基本行われない 38Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 39. Data race : コードと CPU 命令の乖離 (1) ○ 下の処理中でコンテキストスイッチとなった場合、 再開時は昔のメモリを読み込んだ状態で処理再開 される 39 int func(int *ptr) { *ptr++; } int func(int *ptr) { int val = *ptr; val++; *ptr = val; } おおよそ 次のように展開される Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 40. Data race : コードと CPU 命令の乖離 (2) ○ 変数がレジスタ幅に収まらない場合、メモリ書き込 み途中で他スレッドから読み取られる可能性がある ○ 矛盾した状態を読み込んでしまう 40 struct St { int64_t a; int64_t b; }; int set(St *ptr) { *ptr = { 123, 125 }; } おおよそ 次のように展開される struct St { int64_t a; int64_t b; }; int set(St *ptr) { ptr->a = 123; ptr->b = 125; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 41. Data race : CPU キャッシュ (1) 41 メインメモリ (DRAM) L3 キャッシュ L1 キャッシュ L2 キャッシュL2 キャッシュ L1 キャッシュ Core 1 Core 2 ○ メモリアクセスは遅いのでキャッ シュ階層を設ける ○ 容量と速度の要請から複数段に分か れている ○ Core に近いキャッシュは Core ごと に用意されている Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 42. Data race : CPU キャッシュ (2) 42 メインメモリ (DRAM) L3 キャッシュ L1 キャッシュ L2 キャッシュL2 キャッシュ L1 キャッシュ Core 1 Core 2 ○ ある Core でのメモリ書き込みが他 の Core に見えるまでには時間がか かる ○ 左図では最速 44 clock 先 ○ 異なる Core で同じアドレスを読み 込んでいた場合、自分のキャッシュ にある値を読み込み書き込みに気が 付かない4 clocks 11 clocks 22 clocks たくさん レイテンシ write 時間をかけて伝わる Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 43. CPU に必要な機能 ○ メモリを直接操作する ○ ある Core での操作が他の Core にすぐ見える ○ キャッシュの整合性を保つ ○他の Core をストールさせる ○キャッシュ間の同期をとる 43Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 44. Intel X86 CPU 命令 ○ LOCK XADD [mem] r ○ r = [mem], [mem] = [mem] + r ○ LOCK CMPXCHG [mem] r eax ○ if (eax == [mem]) { [mem] = r } else { eax = [mem] } ○ これらの命令を使うことで core 間の同期をとりつつ処理できる 44Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 45. C++ atomic 変数 ○ Atomic CPU 命令をラップしてくれるクラス ○ 変数への操作を適切な atomic CPU 命令に変換してくれる ○ アーキテクチャによって提供されるビット幅等が違う 45 std::atomic<int> val = 128; void func() { int chk = 256; val.compare_exchange_weak(chk, 1024); // lock cmpxchg val++; // lock xadd } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 46. C++ atomic 変数 ○ 利点 : data race を除去できる ○ 欠点 : ある程度のオーバーヘッドがある ○ 常にメモリ上に変数が配置されるうえに Cache の整合性を保つ処理が入る ○同じキャッシュラインへの操作はストールする ○ 使い方 ○ #include <atomic> する ○ atomic にしたい変数を std::atomic<type> とする ○アーキテクチャによって type に入れれる型は違う 46Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 47. 応用 :lock-free アルゴリズム ○ Compare and Swap (CAS) を利用して読み取り値が変わらない場合のみ操作成功 させる ○ Intel CPU の命令は CMPXCHG だが一般的な用語は Compare and Swap ○ 操作中に割り込みが入った場合 CAS が成功しないので (事前に読み取った値と異な る値が返される) 成功するまでリトライを繰り返す 47Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 48. Lock – free アルゴリズム例 ○ 現在値が引く値よりも大きければ引く操作 ○ Compare and exchange に成功すれば ret には tmp が入るはず ○ (ret == tmp) で成功判定できる 48 std::atomic<int> val = 128; void minus(int sub) { int tmp = 0; int ret = 0; do { ret = tmp = val; if (sub <= tmp) { ret = val.compare_exchange_weak(tmp, tmp - sub); } } while (ret != tmp); } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 49. 応用 : SpinLock ○ Mutex と機能は同じだがビジーウェイトによってロック解放を待つ ○ ロック対象処理が短い場合に Mutex よりも反応性がよい ○ シングルコア CPU では意味がない ○ 実装は atomic 変数の操作で行う 49Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.
  • 50. SpinLock 実装 50 class spinlock { private: std::atomic_flag state_; public: spinlock() : state_(ATOMIC_FLAG_INIT) {} void lock() { // busy-wait で現在の状態をロック状態にする while (state_.test_and_set(std::memory_order_acquire)); } void unlock() { state_.clear(std::memory_order_release); // 値をアンロック状態にする } }; int func() { static spinlock lock; std::lock_guard<spinlock> lk(lock); static int val = 0; return val++; } Copyright © PIXELA CORPORATION. All Rights Reserved.|PIXELA CORPORATION PROPRIETARY AND CONFIDENTIAL.