Archive for 3月 30th, 2017

非同期処理について

木曜日, 3月 30th, 2017

 こんにちは、naoyaです。

 毎月一回のプログラミング学習記事の投稿になります。

 第6回(最終回)は、「非同期処理」について、調べたことをまと
めていこうと思います。

・マルチスレッド
  スレッドとは、一連の処理の流れのことを言う。処理の流れが
 一本道なものをシングルスレッド、複数の処理を並行して行うも
 のをマルチスレッドという。
  何か非常に時間のかかる処理があるとすると、処理を行ってい
 る間、計算に専念してもいいならシングルスレッドで問題ないが、
 計算中に他の入力を受け付けたい場合がある。アクションゲーム
 などでは、キャラクターの動きの計算をしている間、ユーザーか
 らの入力を受け付けないようでは、アクションゲームとして成り
 立たない。このような場合、ユーザーからの入力を受け付けるス
 レッドと計算を行うスレッドを並行して動かす。
  要するに、重たい処理を行っている間でもプログラム全体がフ
 リーズしてしまわないようにするために、複数の処理を並行して
 行うのが、マルチスレッドプログラミング。
 
 ・C#におけるマルチスレッドプログラミング
   多くの場合、C#ではスレッドを直接作ることはほとんどない。
   スレッドの新規作成やスレッド間の処理の切替は、結構重た
  い処理で、最小限に抑えたい。そこで、実際にはスレッドを直
  接使うのではなく、一度作ったスレッドを使いまわす仕組み
  (スレッドプール)を使う。
  
・排他制御
  マルチスレッドプログラムでは、複数のスレッドが一つのデー
 タに対して操作することがある。何も考えず、ただ素直にプログ
 ラミングを行うと、意図しない結果になる場合がある。
  そのような問題を解決するために、排他制御というものが必要
 になってくる。排他制御とは、複数のスレッドが同時に一つの
 データを読み書きしないように制御することをいう。
 ・C#における排他制御
   スレッドの排他制御を行う為には、同期オブジェクトと排他
  ロックという概念を用いる。考え方としては、排他制御が必要
  になる部分に入る前に、あるオブジェクトに鍵をかける。鍵が
  かかっている間、他のスレッドは同じオブジェクトには鍵をか
  けることができず、鍵が外されるまで待たされる。そして、鍵
  をかけたスレッドが排他制御が必要な部分を抜けると、鍵を外
  す。
   鍵をかけるオブジェクトを「同期オブジェクト」、鍵をかけ
  る行為を「排他ロック」という。
  
・非同期処理の種類
  「非同期処理」といっても、いくつかタイプがあり、それぞれ
 書き方などが異なる。大まかにいうと、以下の用途がある。
  ・バックグラウンド処理:負荷の高い計算や、I/O待ちなどで、
  CPUやスレッド資源を保持し続けないために、別スレッドで計
  算やI/O待ちを行う。
  ・並列計算:マルチコアCPUの性能を最大限引き出すために、
  同じ計算を複数のコアで同時に実行する。
   ・データ並列:同じ処理を異なるデータに対して行う。
   ・タスク並列:異なる処理が独立して動いていて、その間に
   非同期でデータのやり取りを行う。
 ・バックグラウンド処理
   負荷の高い計算やI/O待ちをする場合、メインスレッドとは
  別のスレッドを使いたい場合がある。例えば、GUIアプリの場
  合、メインスレッドで時間のかかる処理を行うと、アプリがフ
  リーズしてしまい、ユーザーに与える印象が非常に悪くなって
  しまう。メインスレッド以外で行う処理の事を、バックグラウ
  ンド処理という。
   バックグラウンド処理では、バックグラウンドで行った処理
  の結果の値を受け取って、メインスレッドで処理を行いたい場
  合が多い。
  ・利点
    GUIの応答性向上:時間のかかる処理を行っている間、UIス
   レッド(GUIにおける、エンドユーザーからの入力を受け付け
   るためのスレッド)をブロックせず、フリーズを回避できる。
    スレッド資源の節約:I/O待ちにしている間、スレッドを解
   放することによって、メモリ(スレッド用のスタック等)やCP
   U(コンテキストスイッチ等)の負担を減らせる。
 ・データ並列
   並列処理も、非同期処理の一種になる。並列処理を行いたい
  動機は、マルチコアCPUの性能を最大限に引き出すこと。その
  一番シンプルな方法は、同じ処理を、異なるデータに、複数の
  コアで同時に実行すること。このような並列処理を、データ並
  列と呼ぶ。
 ・タスク並列(非同期データフロー)
   並列処理を行うもう一つの方法としては、異なる処理(タス
  ク)を独立して動かして、その間で、非同期でデータのやり取
  りを行う方法がある。異なるタスクを並列に動かすという意味
  では、タスク並列。非同期でデータをやり取りするという意味
  では、非同期データフローと呼ばれる。
  
  
 今回マルチスレッドについて学ぶよりも前に、一度開発でマルチ
スレッドを扱う機会があり、学びなおすにあたって、その時にやっ
ていた事を思い出しながら学ぶことができました。「この失敗は前
の時やってたな」とか思う部分もあり、そういった部分を今回学び
なおせたので、次回マルチスレッドを使う機会があれば、こういっ
た失敗をしないように、気を付けていこうと思います。

 今回で一応最終回となりますが、勉強は続けるので、もしかした
らどこかのタイミングで何か書くかもしれません。その時はまた、
アドバイスなどをよろしくお願いします。

参考URL:
http://ufcpp.net/study/csharp/