あるべるのIT関連メモ

素人エンジニアが何かするときに困ったものなどを参考程度にメモっておこうかと

pthreadの使い方

pthreadについて理解したことのメモ

pthreadとは

POSIXスレッドとはスレッドのPOSIX標準である。
スレッド生成やスレッド操作のApiを定義している。
POSIXスレッド - Wikipedia

・・・つまりマルチスレッドプログラミングができるようになります。

gccオプション

gccコンパイルするためには"-pthread"オプションをつけます。

新しいスレッドを作成する

pthread_create()関数を使います。

int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)

2つめのAttribute引数の意味はよく分かっていませんが、NULLを指定することでデフォルトとなるようです。

#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>

void *thread_func(void *param)
{
    printf("thread_func started\n");
}

int main(int argc, char *argv[])
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_func, NULL);
    if (ret != 0) {
        printf("pthread_create() failed.\n");
    }
    printf("pthread_create() called.\n");
    pthread_join(thread, NULL);    // threadの終了を待つ.
                         
    return 0;
}

出力

>./a.out
pthread_create() called.
thread_func started

main関数でpthread_create()でthreadを作成、指定したthread_funcが呼び出されています。

排他

スレッドの排他を実現するためにmutex(MUTual EXclusion)が用意されています。

int pthread_mutex_lock(pthread_mutex_t &mutex)
int pthread_mutex_unlock(pthread_mutex_t &mutex)

mutexでロックされている区間では同時に1つのスレッドしか操作ができません。
ロックしたら必ずアンロックもセットで行います。

pthread_mutex_t mymutex;
void process(void)
{
    pthread_mutex_lock(&mymutex);
    // 何か処理.
    pthread_mutex_unlock(&mymutex);
}

あるスレッドにてmymutexがロックされている間
他のスレッドはmymutexのロックの取得ができないため
pthread_mutex_lockで待ち状態になります。

条件変数

mutex区間で何か条件の成立を待ちたい、そんなときはpthread_cond_wait()を使用します。
mutexのlock/unlockと同じように
pthread_cond_signal()(またはpthread_cond_broadcast())とセット使用します。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_signal(pthread_cond_t *cond);

これがめちゃ難解でした(のでこれを書いている)。

まず条件の成立を待つ側はpthread_cond_wait(&mycond, &mymutex)を呼び出します。
pthread_cond_wait()は呼ばれるとまず最初にmymutexのロックを解除します。
こうして他のスレッドがmymutex区間にアクセスできるようにします。
そして条件mycondを待ちます。

ここでmymutexのロックが解除されているので
別のスレッドはmymutexのロックを取得して処理を行います。
それによってmycondが成立した場合にpthread_cond_signal(&mycond)を呼び出します。

するとmycondを待っている最初のスレッドがこの時点で目覚めます。
またこのときpthread_cond_wait()はmymutexのロックを再取得します。
mymutexのロックが取得できた後に初めて応答し、最初のスレッドの処理を続行させます。

// スレッド1がmymutexのロックを取得
pthread_mutex_lock(&mymutex);

// ある条件が整うまで以下を呼び出し待つ
// ここでmymutexのロックは解除される(pthread_mutex_unlock(&mymutex)が実行される)
pthread_cond_wait(&mycond, &mymutex);

// スレッド2がある条件を成立させたのでスレッド1を起こす
// このときpthread_cond_waitはpthread_mutex_lock(&mymutex)が可能になるまで応答しない
pthread_cond_signal(&mycond);

こちらを参考にしました。
一般的なスレッド: POSIX スレッドの説明: 第3回