【マルチスレッド=浮気!?】実際にC++でプログラムしてみた。>プログラミング【マルチスレッド=浮気!?】実際にC++でプログラムしてみた。2020年2月4日レイヤーが低い分野では特に、マルチ○○○という言葉をよく聞きます。マルチスレッド、マルチプロセス、マルチコアなどなど、結構思い浮かぶかと思います。本質はどれも「並列、同時に」ということです。様々なプロセスがあり、その一つに「恋愛」があります。破局すれば次の女性・・・これでは「女性経験値」を効率的に上げられないですよね。忘れてならないxxxの意味を言うとします。多くの女性スレッドを抱えます。上手いこと関係性を気づいていく。浮気が上手く機能するわけです。本命にバレる可能性が高まります。※浮気を推進しているわけではありません(笑)(残念ながら??)私は、そんな器用なことは出来なので、シングルスレッドな男になります。マルチスレッドプログラミングも同じです。予期せぬ結果が返ってくるわけです。本命に刺されるかもしれません。各スレッドの扱いは基本的に平等ですけど。ここで簡単に「マルチ○○○」という言葉をおさらいしておきましょう。スポンサーリンクコアとスレッドとプロセスの違いイメージで言うならば、プロセスが1つのアプリケーションでその中にいくつかのスレッドがあるといったところでしょう。厳密にはプロセスとスレッドには、リソースの扱い方の違いなどがありますが、ざっくり言ってどちらも一つの処理単位です。CPUが全く同時に処理できるプロセス数もスレッド数もCPU性能によって限度があります。瞬間的に切り替わりながら、あたかも全く同時にプログラムが動作しているかのように振る舞います。性能指標が書いてあります。これは1つのCPUに4コアあり、そして最大8スレッドをCPUが全く同時に扱えるということを意味しています。基本、1コアで扱えるのは1プロセスです。「プロセス」はプログラムつまりソフトウェア上の言葉です。実際に見てみましょう。webブラウザと数個のソフトを同時に立ちあげているときのCPUの様子(タスクマネージャ)です。多くのプロセスとスレッドが生成され、それらが処理されているのが分かるかと思います。まとめると、CPUにはコアがあり、"コア"でプロセスを扱い、"プロセス"でスレッドを扱います。どの程度の数を一度に扱えるかは、CPUの性能によります。全てOSに気まぐれ次第になります。それでは実際にC++で、マルチスレッドをやってみましょう。Linuxを使うのでご用意を。マルチスレッド:pthreadライブラリスレッドを意識していない入門的なプログラミングは、1スレッドだけのプログラムに該当します。マルチスレッドプログラミングをするために、ここでは「pthreadライブラリ」を使います。<pthread.h>をインクルードします。様々な変数と関数が用意されています。入門として使うものだけを、ソースコードの説明と同時に紹介します。マルチスレッドではない、1スレッドのプログラムです。「1からnまでの和を出力する関数」を用意しました。main文でその関数を呼び出す、という簡単なプログラムです。0;}関数を呼び出すときに、どの数まで足すか指定します。これは10000までの和計算を一回しか行ってないです。普通は10000を指定した関数の次に、30000を引数にした関数を呼びます。10000が終わって30000を計算していては非効率ですよね。10000までの和を求めるスレッドと30000までの和を求めるスレッドを作って、並列に計算してみましょう。マルチスレッドのソースがこちらです。新しくスレッドを作るために、まずpthread.hをインクルードします。実際にスレッドを作るときは、pthread_t型の変数を宣言して、スレッドの入れ物を用意します。これにはスレッドの識別IDが入ります。実際にスレッドを動作させるときは、pthread_create関数を使います。*arg);第一引数:スレッドIDのポインタ第二引数:作成するスレッドの属性を指定するパラメータ。通常はNULL(デフォルトの属性)。第三引数:スレッドで実行したい関数ポインタ。関数のフォーマットは、void型ポインタを仮引数にとり、void型を戻り値とする必要がある。第四引数:第三引数で指定した関数の引数。pthread_createで関数を実行したら、そのスレッドは終了します。OSが保持するコンテキスト切り替えに必要なスレッド情報を破棄させます。pthread_join関数を使います。**value_ptr);第一引数:pthread_t型変数、スレッドID第二引数:スレッドの戻り値の格納先を指定。今回は不必要なのでNULLを指定。以下のようになってしまいます。ちなみに、pthreadライブラリを使用する時は、gccでコンパイルするときに、-pthreadオプションを付けて下さい。10000までの和は500500030000までの和は450015000が正しい結果となります。間違った結果が返ってくるときもあります。これでは正しいプログラムとは言えないです。以下のことが原因となっています。原因の話に入る前に、メモリと変数の説明を少しします。スレッドはそのプロセスが保持するアドレス空間を全スレッド間で共有します。プロセス間では、アドレス区間を共有しません。sum変数はプログラムの冒頭で、グローバル変数として宣言しています。グローバルで宣言された変数や配列は、メモリのデータ領域に確保されます。ちなみに関数内で宣言された変数は、メモリのスタック領域に確保されます。このデータ領域にある変数は、どのスレッドからでもアクセス可能です。スタック領域もポインタを渡すなり、アドレス空間を共有しさえすれば疑似的に可能です。他の記事に任せるとしましょう。並列処理をしながら、お互いにsum変数にアクセスしています。この一文をアセンブリ的に見てみましょう。メモリからsumに格納された値をレジスタAに格納する。メモリからxに格納された値をレジスタBに格納する。レジスタAとレジスタBを足して、結果をレジスタAに格納する。レジスタAの値をsumが示すメモリに書き込む。ソースコード上では一行に見えても、CPUとメモリ内では上記の4行の処理が起きています。本来は期待しないsumの値が読み込まれたり書き込まれたりします。したがってあるスレッドがsumを使っている間は他のスレッドは、sumを使えないようにする必要があります。これを排他制御と言います。排他制御は次の記事で書こうかと思います。最後まで読んでいただきありがとうございました。※今回のプログラムは、マルチスレッドのプログラミングを分かりやすい例で行うために、あえてsumをグローバル宣言しました。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。date*日本語が含まれない投稿は無視されますのでご注意ください。調べたのでその備忘録です。簡単なWebサーバを実装してみます。HTTPサーバと呼ぶべきでしょうか。ARPエントリーを取得して表示させてみました。そのままCで実装したいと思いまいした。いう規格に基づいて通信が行われます。認識させるには、ビーコンフレームを使います。IPv6を取得して標準出力させてみます。...PREVArduinoでDC/AC電源の電力制御を行う方法(理論)NEXT【C++】マルチスレッドでMutex(排他制御)をやってみたプロフィール某名門大の大学院生です。IoT、人口知能、ネットワークインフラ系まで幅広く興味があります。いう方のために簡単にまとめてみました。IPv6を取得して標準出力させてみます。自分の目で調査したのでまとめます。変更までする方法をご紹介します。ioctlシステムコールを使います。フラグを引数に指定します。一度まとめておこうと思います。以下が思いつくかと思います。全て"stdio.h"に定義されています。