Win32APIにおけるマルチスレッドについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Integral

Win32APIにおけるマルチスレッドについて

#1

投稿記事 by Integral » 8年前

とある本に掲載されているブロック崩しのサンプルプログラムについての質問です。
質問したいソース全文を貼り付けたいところですが、ソースには著作権がありますので、それはできそうもありません。
このような質問をするのは自分としても不本意なのですが、ある程度省略した形で疑問点のある部分のみを質問させて下さい。

ブロック崩しの内容は一般的なもので、プレイヤーが自分のバーを操作し、バーにボールがぶつかれば跳ね返り、上にあるブロックに当たればあたったブロックは消滅します。
疑問に思ったのはボールの動きについての処理をマルチスレッド化しているところです。

このボールの動きについて関するスレッドはWM_CREATEが生じた際にウィンドウプロシージャで作られ、その内容は次のようなものです。
(質問に直接関係ない型、引数、返り値等は省略しています。)

ThreadFunc() {
while(isRun) {
MoveBall();
InvalidateRect();
Sleep();
}
}

MoveBall()でボールの座標を表すグローバル変数をインクリメントあるいはデクリメントし、ボールの動きを表現するとともに、バー、壁、ブロックとの当たり判定を行っています。
InvalidateRect()でWM_PAINTが呼び出されると、バー、ボール、ブロック等の座標を示すグローバル変数にアクセスしそれぞれをウィンドウに描画します。

ここまでなら、なんら問題なくプログラムは動作すると思うのですが、問題はプレイヤーがバーを動かしたときです。
バーはマウスのあるポイントのx座標に移動するような使用です。具体的にはウィンドウプロシージャー内で次のような処理を行っています。

case WM_MOUSEMOVE:
barLocation.x=LOWORD(lParam);
InvalidateRect();
return 0;

barLocationはバーの座標を示すグローバル変数です。
MoveBall関数内においても、このグローバル変数barLocationにアクセスしてボールとの当り判定をしています。

この「ウィンドウプロシージャー内のbarLocationへのアクセス」と、「ThreadFunc関数内のbarLocationへのアクセス」がゲーム中に同時に起こるという可能性があると思うのですが、その場合データの整合性が失われてしまったりはしないのかな?と思いました。

ミューテックスなどを用いて、同期を行っている記述があれば納得もできるのですが、そういった記述はソース内に見当たりません。
自分のマルチスレッドのメモリアクセスについての認識が間違っているのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: Win32APIにおけるマルチスレッドについて

#2

投稿記事 by softya(ソフト屋) » 8年前

barLocation.xを同時にアクセスしたとしてもint型の場合4バイトの書き換え途中でスレッドに切り替わることは無いのでスレッドが1つ古い情報を見ることはあっても破綻はしないと思います。
そういう意味ではギリギリOKな作りかたと言えると思いますが、OSやCPUのハードに依存した書き方と言わればそのとおりです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Integral

Re: Win32APIにおけるマルチスレッドについて

#3

投稿記事 by Integral » 8年前

つまりint型では4バイトという小さい領域を書き換えるに過ぎないから、そこで同時アクセスすることはない…という意味でしょうか?
ではどのような場合にデータの整合性が失われてしまうのでしょう?

自分は趣味でRTSを開発しています。
リアルタイムなゲームの場合メインループは、

入力→AI→描画→(入力へ)

という形になると思います。AIでの計算量がごく短時間で終わる場合何の問題もありません。しかしAIで大多数のキャラクターを処理し、それぞれが一斉に動くようなゲームの場合、AIをメインループに入れるとウィンドウが固まってしまうのではないかと思いました。AIをマルチスレッド化しようと思い、実は以前やってみたのですが、よく分からないバグが多発し(おそらくは入力・AI・描画全てで不正なアクセスが起こり、データの整合性が失われた。)この方法をあきらめました。

この辺りの知識をもっと深めたいのですが、どこを探してもあまりこれに精通した書籍は見当たりません。
どうやってこの分野の知識を得ればよいのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: Win32APIにおけるマルチスレッドについて

#4

投稿記事 by softya(ソフト屋) » 8年前

基本的には機械語一命令で書き出せないデータは同期処理(例外有り)が必要になります。
テクニックを駆使して複雑なことをやっても難易度の高いバグに悩まされるだけなので、同時参照するデータはコンパクトに纏める事とクリティカルセクションなどで同時アクセスをしないように工夫する事から始めてみてはどうでしょうか?
あるいは、AIスレッド用のデータ領域を用意してデータ設定。AIスレッドを起動。AIスレッド終了間際にメッセージで終了を通知。メッセージを受けてAIスレッド用のデータ領域を参照するという手順でやれば矛盾しないはずです。
Integral さんが書きました:この辺りの知識をもっと深めたいのですが、どこを探してもあまりこれに精通した書籍は見当たりません。
どうやってこの分野の知識を得ればよいのでしょうか?
私の知る限りでは何冊かあります。
「Amazon.co.jp: 並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング: Clay Breshears, 千住 治郎: 本」

「Amazon.co.jp: Visual C++.NETではじめるWin32APIシステムプログラミング: 北山 洋幸: 本」


あとWin32API関連ならほぼ説明されています。
「Amazon.co.jp: Win32API完璧マスタ―Visual C++プログラミング: 土井 滋貴, 上田 悦子, 那須 靖弘: 本」

「Amazon.co.jp: APIで学ぶWindows徹底理解―できるプログラマになるための (日経BPパソコンベストムック): 安室 浩和, 日経ソフトウエア編: 本」
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Integral

Re: Win32APIにおけるマルチスレッドについて

#5

投稿記事 by Integral » 8年前

なるほど、今の自分の知識ではマルチスレッドはまだレベルが足りないようです(--;)
参考文献の紹介ありがとうございました。

当面、開発のほうはシングルスレッドで進めますが、余力のあるときに教えてもらった書籍でマルチスレッドの勉強をしてみようと思います。(正直何を読んで学んでいいか分からなかったため、八方塞がりでした…)

回答ありがとうございました。とりあえず解決です!

アバター
lriki
記事: 88
登録日時: 9年前

Re: Win32APIにおけるマルチスレッドについて

#6

投稿記事 by lriki » 8年前

ゲームに限ってであれば、

「西川善司の3Dゲームファンのための「ロスト プラネット」グラフィックス講座」
http://game.watch.impress.co.jp/docs/20070131/3dlp.htm

こちらのページの「■ 実はゲームはマルチスレッド向きだった!」
のセクションが参考になると思います。

閉鎖

“C言語何でも質問掲示板” へ戻る