0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

古典的C++プログラマのためのModern C++つまみ食い : アトミック操作

Posted at

C++11以降のC++はModern C++と言われ、それ以前のC++(古典的C++)に対して多くの言語仕様が追加された。古典的C++しか知らないプログラマがModern C++の言語仕様を使い倒したコードを見ても、さっぱり分からないかもしれない。
古典的C++を主戦場とするプログラマに対して、盲目的にModern C++に移行すべきだと言うつもりはない。ただ、Modern C++は古典的C++の上位互換であり、古典的C++の枠組みで書かれたコードに対してModern C++の一部の仕様をつまみ食い的に利用するだけでも、おいしいことはある。
そこで、古典的C++の枠組みでコードを書くプログラマがつまみ食いする価値のあるModern C++の仕様について、いくつかの記事に分けて紹介していく。

アトミック操作

C++11では、マルチスレッドでアトミックに変数にアクセスする機能がある。
std::atomic<変数の型> 変数名; のように変数を宣言すれば、その変数はアトミックにアクセスできる。

下記は、マルチスレッドで0から9999までの数字を順番に出力するプログラムで、変数Aへのアトミックなアクセスが保証されていれば、値の重複や抜けは発生しない。

//#define ENABLE_ATOMIC  // アトミック性を保証する時は有効化する

#include <stdio.h>
#include <pthread.h>

#ifdef ENABLE_ATOMIC
#include <atomic>
std::atomic<int> A;
#else
int A;
#endif


static void* start_routine(void*) {
    for (int loop = 100; loop !=0; loop--){
        int a = A++;
        printf("%d\n", a);
    }
    return nullptr;
}

static const int NUM_THREAD = 100;
int main() {
    printf("\n");
    A = 0;
    pthread_t th[NUM_THREAD];
    for (int i = 0; i < NUM_THREAD; i++) {
        pthread_create(&th[i], nullptr, start_routine, nullptr);
    }
    for (int j = 0; j < NUM_THREAD; j++) {
        void* retval;
        pthread_join(th[j], &retval);
    }
    return 0;
}

上記プログラムをENABLE_ATOMICマクロを定義せずにコンパイルして実行すると、出力される値が重複することが起きる。複数のスレッドからの変数Aへのアクセスが競合してしまうことがあると考えられる。

$ g++ -std=c++11 atomic.cc -lpthread -O0
$ ./a.out | sort -n | uniq -D
5166
5166
$ ./a.out | sort -n | uniq -D   (たまたま競合していない場合)
$ ./a.out | sort -n | uniq -D
5214
5214
$ ./a.out | sort -n | uniq -D   (たまたま競合していない場合)
$ ./a.out | sort -n | uniq -D
6896
6896
6961
6961

ENABLE_ATOMICマクロを定義してこのプログラムをコンパイルして実行すると、何回実行しても出力される値が重複することは起きず、変数Aへのアトミックなアクセスが行われていることが分かる。

$ g++ -std=c++11 atomic.cc -lpthread -O0 -DENABLE_ATOMIC
$ ./a.out | sort -n | uniq -D
$ ./a.out | sort -n | uniq -D
$ ./a.out | sort -n | uniq -D
$ ./a.out | sort -n | uniq -D
$ ./a.out | sort -n | uniq -D
$ ./a.out | sort -n | uniq -D
$
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?