IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

pthread 勉強

だらだら書くよ

初めてのコード

#include <pthread.h>

void* f(void* p) {
    puts("hello");
    sleep(1);
    puts("hello");
    sleep(1);
    puts("hello");
}

int main(int argc, char** argv) {
    pthread_t thread;
    pthread_create(&thread, NULL, f, (void*)NULL);
    pthread_join(thread, NULL);
}
$ gcc p.c -lpthread && ./a.out
hello
hello
hello
$

おおお。スレッドスレッド

みゅーてっくつ

#include <pthread.h>

// みゅーてっくつ
pthread_mutex_t m;

void* f(void* p) {
    int i;
    for (i = 0; i < 10; i ++) {
        // こっから
        pthread_mutex_lock(&m);
        putchar('h');
        sleep(0);
        putchar('e');
        sleep(0);
        putchar('l');
        sleep(0);
        putchar('l');
        sleep(0);
        putchar('o');
        sleep(0);
        putchar('\n');
        pthread_mutex_unlock(&m);
        // ここまで
        // クリティカルセクション
    }
}

int main(int argc, char** argv) {
    // みゅーてっくつの
    // 本当は返り値を判定すべき
    // 返り値が 0 だと成功
    pthread_mutex_init(&m, NULL); // ← この NULLが気になって死ぬ

    pthread_t thread0;
    pthread_t thread1;
    pthread_create(&thread0, NULL, f, (void*)NULL);
    pthread_create(&thread1, NULL, f, (void*)NULL);
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);

    // 後始末
    pthread_mutex_destroy(&m);
}

実行!

$ gcc p.c -lpthread && ./a.out
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
$

うひょー!
ロックしてる部分をコメントアウトしてみる

void* f(void* p) {
    int i;
    for (i = 0; i < 10; i ++) {
        // pthread_mutex_lock(&m);
        putchar('h');
        sleep(0);
        putchar('e');
        sleep(0);
        putchar('l');
        sleep(0);
        putchar('l');
        sleep(0);
        putchar('o');
        sleep(0);
        putchar('\n');
        // pthread_mutex_unlock(&m);
    }
}
$ gcc p.c -lpthread && ./a.out
hheelllloo
h
heelllloo
h
heelllloo
h
heelllloo
h
heelllloo
h
heelllloo
h
heelllloo
h
heelllloo
h
heelllloo
h
heelllloo

$

わー!バラバラ!
みゅーてっくつ!
てっくつ!てっくつ!

pthead_mutex_init の第二引数

気になる
そんなときは、

$ man pthread

pthread_mutex_init のところには

     int pthread_mutex_init(pthread_mutex_t *mutex, const
                        pthread_mutexattr_t *attr)
                        Initialize a mutex with specified attributes.

って書いてあった
よくわからん><
ググるカスσ(・∀・;)
こんなページみっけた
http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/pthread_mutexattr_settype.3.html

    pthread_mutex_init (&m, NULL);

    pthread_mutexattr_t mattr;
    pthread_mutexattr_init(&mattr);
    pthread_mutex_init(&m, &mattr);
    pthread_mutexattr_destroy(&mattr);

と同じってことね。
で mattr の値を変えるときは、
pthread_mutexattr_setprioceiling
pthread_mutexattr_setprotocol
pthread_mutexattr_settype
を使うのか。

じゃあ再帰ロックちゅーのを試してみる

さっきのループを強引に再帰

#include <pthread.h>

// みゅーてっくつ
pthread_mutex_t m;

char* s = "hello\n";

void* f(void* p) {

    int count = (int)p;
    if (count == 10) return;
    pthread_mutex_lock(&m);

    putchar('h');
    sleep(0);
    putchar('e');
    sleep(0);
    putchar('l');
    sleep(0);
    putchar('l');
    sleep(0);
    putchar('o');
    sleep(0);
    putchar('\n');

    // わざわざココで再帰(ロックの中でロック)
    f((void*)(count + 1));

    pthread_mutex_unlock(&m);
}

int main(int argc, char** argv) {
    pthread_mutexattr_t mattr;
    pthread_mutexattr_init(&mattr);

    // ここで、再帰ロック可能ねって言ってる
    pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);

    pthread_mutex_init(&m, &mattr);
    pthread_mutexattr_destroy(&mattr);

    pthread_t thread0;
    pthread_t thread1;
    pthread_create(&thread0, NULL, f, (void*)0);
    pthread_create(&thread1, NULL, f, (void*)0);
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);

    pthread_mutex_destroy(&m);
}

じゃあ、実行!

$ gcc p.c -lpthread && ./a.out
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
$

わー!
ロックの中でロックできてる
ろっけんろー
じゃあ、以下の行をコメントアウトしてみる

    //pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
$ gcc p.c -lpthread && ./a.out
hello

(固まる)

おおおお。
ちゃんと動かなかった!

次は、せまふぉ

(ここで、はてながメンテになって書けなかった><)