Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

マルチスレッドのConditionについて

はじめに

core.sync.condition.Condition
「え?ただのConditionだよ?知ってるよね?」みたいに書かれてる。
つらい。

Conditionとは

Java由来?のマルチスレッドの同期システムです。Javaとか滅せ。
コンストラクタの引数にしたMutexを使って、ロックの解除を待ったり、通知を待ったりします。
Conditionでwaitした場合、Mutexがロックされていなくて、かつConditionに通知(notify)されるまでスレッドを停止します。

例(1) ロック中にwaitした場合

Mutexをロックしているときにwaitすると、そのMutexのロックを解除して、待機状態に入ります。別スレッドがMutexをロックすると、notifyされても、Mutexがロック解除されるまでは待機を維持します。

import std.stdio, std.parallelism, core.thread, core.sync.condition, core.sync.mutex;

void main()
{
    auto cond = new Condition(new Mutex);

    //     000    100    200    300    400    500    600 [ms]
    // 1:  1xxxxxxxxxxxxxooooooo-------6xxxxxx7     8!
    // 2:         2------xxxxxx3!4xxxx5oooooooooooooo9
    // 【凡例】
    //     x : ロック中
    //     - : 他のロック解除待ち
    //     o : 他からの通知待ち
    //     ! : 通知

    //     000    100    200    300    400    500    600 [ms]
    // 1:  1xxxxxxxxxxxxxooooooo-------6xxxxxx7     8!
    taskPool.put(task(
    {
        Thread.sleep(0.msecs);
        writeln(1);
        cond.mutex.lock();
        Thread.sleep(200.msecs);

        // ここで一度ロックが外れる
        // →3での通知を受けて再度ロックを試みて解除を待つ
        //   →5でロック解除されて制御が戻る
        cond.wait();

        writeln(6);
        Thread.sleep(100.msecs);

        writeln(7);
        cond.mutex.unlock();

        Thread.sleep(100.msecs);
        writeln(8);
        cond.notify();
    }));
    //     000    100    200    300    400    500    600 [ms]
    // 2:         2------xxxxxx3!4xxxx5oooooooooooooo9
    taskPool.put(task(
    {
        Thread.sleep(100.msecs);

        writeln(2);
        cond.mutex.lock();

        Thread.sleep(100.msecs);
        writeln(3);
        cond.notify();
        writeln(4);
        Thread.sleep(100.msecs);
        writeln(5);
        // ここで一度ロックが外れる
        // →8での通知を受けて再度ロックを試みてロック成功
        cond.wait();

        writeln(9);
        cond.mutex.unlock();
    }));
    taskPool.finish();
}

例(2) ロック解除中にwaitした場合

ロック解除中にwaitした場合、ほかのスレッドからnotifyされるまで待機します。

import std.stdio, std.parallelism, core.thread,
       core.sync.condition, core.sync.mutex;

void main()
{
    auto cond = new Condition(new Mutex);

    //     000    100    200    300    400    500    600 [ms]
    // 1:  1ooooooooooooo-------6xxxxxx7     8!
    // 2:         2xxxxx3!4xxxx5oooooooooooooox9
    // 【凡例】
    //     x : ロック中
    //     - : 他のロック解除待ち
    //     o : 他からの通知待ち
    //     ! : 通知

    //     000    100    200    300    400    500    600 [ms]
    // 1:  1ooooooooooooo-------6xxxxxx7     8!
    taskPool.put(task(
    {
        Thread.sleep(0.msecs);
        writeln(1);

        // 通知待ち
        // →3での通知を受けてロックを試みて解除を待つ
        //   →5でロック解除されて制御が戻る
        cond.wait();

        writeln(6);
        Thread.sleep(100.msecs);

        writeln(7);
        cond.mutex.unlock();

        Thread.sleep(100.msecs);
        writeln(8);
        cond.notify();
    }));
    //     000    100    200    300    400    500    600 [ms]
    // 2:         2xxxxx3!4xxxx5oooooooooooooox9
    taskPool.put(task(
    {
        Thread.sleep(100.msecs);

        writeln(2);
        cond.mutex.lock();

        Thread.sleep(100.msecs);
        writeln(3);
        cond.notify();
        writeln(4);
        Thread.sleep(100.msecs);
        writeln(5);
        // ここで一度ロックが外れる
        // →8での通知を受けて再度ロックを試みてロック成功
        cond.wait();

        writeln(9);
        cond.mutex.unlock();
    }));
    taskPool.finish();
}

D言語特有の問題

Conditionは性質上、当たり前のようにスレッド間で共有される資源です。つまり、sharedストレージクラスにしたくなる時があります。
しかしながら、Condition(をはじめとするcore.sync.*のモジュール)はsharedなメンバ関数を提供していません。
今我々にできる最良の手順は、castによってsharedを外してしまうことです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?