こんにちは!独学プログラマー&ライターのつぶらやです。
本日は、シングルスレッド/マルチスレッドというプログラムの実行方式についてお話していきます。
シングルスレッドは、一つの処理が終わらないと次の処理ができないというプログラムの実行方法です。
マルチスレッドは、一つの処理が終わったらなくても次の処理を行うことが出来ます。
phpはどちらの方式なのかと言いますと、シングルスレッドです。
じゃあ、phpはプログラムは一つずつしか実行できないの?
いいえ、実はphpでもマルチスレッドにすることが出来ます。
次項目から説明していきます。
マルチスレッドのメリットとデメリット
phpはマルチスレッドにする事が出来ると書きました。
ただし、元々シングルスレッドのphpをマルチスレッドにする事は当然、良い点=メリットと悪い点=デメリットがあります。
その事を理解した上で、本当にマルチスレッドにするしかないのか判断してください。
メリット
処理を複数走らせる事が出来るので、処理が速くなる可能性があります。
勿論、これが最大のメリットですね。
例えば、処理A(処理時間1)と処理B(処理時間2)があった場合のマルチスレッドとシングルスレッドの場合を比較してみます。
シングルスレッド
[su_table]
経過時間 | 処理A | 処理B |
経過時間1 | ↓ | - |
経過時間2 | - | ↓ |
経過時間3 | - | ↓ |
[/su_table]
シングルスレッドの場合はトータル処理時間は3でした。
マルチスレッド
[su_table]
経過時間 | 処理A | 処理B |
経過時間1 | ↓ | ↓ |
経過時間2 | - | ↓ |
[/su_table]
マルチスレッドの場合はトータル処理時間は2でした。
このように処理を並列に走らせる事で、処理時間を短縮させられる場合があります。
デメリット
処理が速くなるならば、何でもマルチスレッドにすればいいのに!
と、誰もが考えると思いますが、もちろんそうしないのはいい点ばかりではないからです。
使い方を間違えると、逆に処理が遅くなってしまうケースも存在します。
では実際どのような状況だと処理がおそくなってしまうのでしょうか?
スレッドというのは処理の単位のようなものです。
それがあまりにも多い数に増えたマルチスレッドの場合を考えます。
1台のサーバーなどで処理すると簡単に処理が追い付かなくなります。
メリットデメリットはおわかりいただけましたでしょうか。
次の項目から、具体的な方法を記載していきます。
マルチスレッドにする方法(exec関数を使う)
昔から使われていたexec関数での非同期処理方法でマルチスレッドを実現する方法です。
exec関数自体は、外部のプログラムを実行するというphpの関数です。
exec関数について詳しく知りたい方は以下を確認してください。
それでは、サンプルコードで説明します。
<?php class execMulti { function MultithreadTest() { // 時間がかかる処理 exec("php static_massive.php > /dev/null &"); // ↓ここで他の処理を行ってもよい echo "処理完了"; } } $em = new execMulti; $em->MultithreadTest(); ?>
上記を実行すると、時間がかかる処理が終わる前であっても、処理完了が表示されます。
exec("php static_massive.php > /dev/null &");
「> /dev/null &」で返ってくる値をなくしていますので、レスポンスを待つ事はありません。
そのため処理完了の表示が、時間がかかる処理より早くなります。
ただし、この方法では時間のかかる処理がいつ終わったのかわかりません。
実行のログを取ったり、DBに登録するなどの方法で実行結果を使用者に伝える事を考える事を忘れないようにしましょう。
マルチスレッドにする方法(pthreads)
最後に、PHPの拡張モジュールのpthreads(ピースレッズ)を使う方法をお話します。
前項の、execを使用した方法よりもシンプルに記述する事が出来ると思います。
①環境の準備とphpのインストール
vagrantなどを使ってお好きな環境をご準備ください。
phpはマルチスレッドで動かして安全な実装になっているスレッドセーフ版を使用する必要があります。
公式からスレッドセーフ版のphpをダウンロードします。
以下にアクセスをして、図の赤枠部分からダウンロードをします。
http://www.php.net/downloads.php
また、スレッドセーフでのインストールは、configureオプションで –enable-maintainer-ztsを指定する必要があります。
./configure --enable-maintainer-zts
※必要に合わせて、Apacheやmysqlのオプションもつけましょう。
以下のコマンドでphpのバージョンが確認できたら終了です。
php -v
②pthreadsをインストール
Gitで以下に公開されていますので、zipをダウンロードしましょう。
https://github.com/krakjoe/pthreads/archive/master.zip
zipを解凍して、解凍したファイルに移動後、phpizeを実行します。
以下を実行して、PHP Modulesの一覧にpthreadsが表示されていたら準備完了です。
php -m
環境によってこの辺りの設定は違ってきますので、環境名+pthreadsなどで検索して情報を探してください。
③マルチスレッドで動かしてみる
pthreadsを使用してみましょう。
サンプルコードです。
<?php class pthreadsTest extends Thread { public function run () { sleep(5); } } $ts1 = new pthreadsTest(); $ts1->start(); // Thread::startを呼ぶとnewスレッドが作られ、runが実行される $ts2 = new pthreadsTest(); $ts2->start(); // Thread::startを呼ぶとnewスレッドが作られ、runが実行される ?>
sleep(5)が2回呼ばれているので10秒かかりそうですが、実際は5秒となります。
pthreadsでマルチスレッドが実現できました。
まとめ
今回はphpのマルチスレッドについて書いてみました。
phpはシングルスレッドなので、マルチスレッドにしたいと思う事は少ないかもしれません。
しかし、できる事を多くすることが様々な選択肢と可能性を広げる事になるのだと思います。
是非お手元の環境で試してみてください。
では、また。