1 名前:デフォルトの名無しさん mailto:sage [2007/08/13(月) 21:35:32 ] マルチスレッドプログラミングについて語るスレ。 その1 pc3.2ch.net/tech/kako/997/997345868.html その2 pc5.2ch.net/test/read.cgi/tech/1037636153/ その3 pc8.2ch.net/test/read.cgi/tech/1098268137/ その4 pc8.2ch.net/test/read.cgi/tech/1130984585/ その5 pc11.2ch.net/test/read.cgi/tech/1157814833/ OS・言語・環境は問わないが、それゆえ明記すべし。 テンプレ 【OS】 【言語】 【実行環境】 【その他突起する事項】
666 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 00:40:42 ] それまでの話の流れとは関係ないが 「マルチスレッド対応ライブラリを使用する」と 「マルチスレッドで動作するプログラムにする」は全く違うのだが まさかとは思うが、>>665 はそういう意味じゃないよな? 当然、「コンパイラをマルチスレッドで動作させる」だよね? 一応触れておくと Win32で普通にGUIプログラムを作る場合、明示的にスレッド関連の操作をしない限り マルチスレッドで動くことは無い。 何故なら、メッセージキューが1スレッドに1つ作られるので そこからのイベントで処理を記述する書き方だと、1スレッドにしかならないから。 (イベントハンドラでスレッド操作をすれば当然マルチスレッドも可能) もちろん、カーネル内の処理(割り込み等)は別。
667 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 00:59:30 ] そういえば、Win9xのWinsock2の非同期処理は 内部的にスレッド作って擬似動作させてたんだっけ。 忘れてた。
668 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 01:14:13 ] >>666 メッセージキューも明示的に作る(作らせる)ものであって スレッド作成=メッセージキュー作成じゃないよ。
669 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 12:10:33 ] > メッセージキューも明示的に作る(作らせる)ものであって 具体的にどうやって作るの?
670 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 12:39:33 ] MSDNのPostThreadMessageの所に書いてあるな
671 名前:まあ、明示的がどうかは人によって違うと思うが... mailto:sage [2008/05/04(日) 16:07:57 ] これのことかな... > その後、ポスト先のスレッドで、 > PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) を呼び出し、 > このスレッド用のメッセージキューを強制的に作成します。 でもこれって、 > スレッドが Win32 のユーザー関数または GDI 関数のいずれかを最初に > 呼び出した時点で、システムはそのスレッドのメッセージキューを作成 > します。 ってことだよね。 あまり「明示的」とは思えないんだが...。
672 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 17:10:13 ] 風が吹いたら桶屋が儲かるくらい暗黙的でなければ明示的
673 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 22:53:30 ] いや別にメッセージループに入ったからといって CPUを最後まで占有出来るわけじゃないのだ 途中で強制的に割り込まれる そうすると他のループに権利が渡されるだけだな マルチスレッドでコンパイルすると各メッセージループは完全に独立したスレッドになる だから既存のアプリもほとんどはデュアルコアの恩恵がある
674 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 23:11:24 ] おまえはそんなにメッセージループを作っているのか? 大多数のアプリはWinMainの中のGetMessage1つだけだと思うが
675 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 23:12:03 ] それと、「マルチスレッドでコンパイルする」の意味を具体的に説明しろよ
676 名前:デフォルトの名無しさん mailto:sage [2008/05/04(日) 23:14:14 ] 上の方は、プリエンプティブマルチタスクの解説で、4行目の 「他のループ」=「他のプロセスのメッセージループ」なのかなー と思って読んでいたが >マルチスレッドでコンパイルすると各メッセージループは完全に独立したスレッドになる え?
677 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 00:56:45 ] ちょっぴりエスパー能力を発揮して解読してみた。 普通、「メッセージループ」と言うと while (GetMessage()) { ... } の部分のことを指すと思うのだが おそらくこのヒトは、DispatchMessageで間接的に呼ばれるルーチン、 大抵は「WndProcの呼び出し1回」のことを 「メッセージループ」と呼んでいるような気がする。
678 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 01:18:24 ] だとしてもウインドウプロシージャがマルチスレッドで 並列実行されたりはしないと思うが。
679 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 01:48:05 ] もちろんその通り。 大丈夫、基本的な仕組みを理解してないのは、多分一人だけだから。
680 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 03:39:24 ] え? そうなん? メッセージループをマルチスレッドでコンパイルしたら 完全にプリエンプティブなマルチコアになるでしょ
681 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 05:18:58 ] だからその「マルチスレッドでコンパイル」って、何をどうすることなの?
682 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 05:34:27 ] 一応、>>666 の前半部に、候補としていくつか挙げてあるけど ・マルチスレッドライブラリを使用する(コンパイラオプションを設定) ・マルチスレッドで動作するようにソースコードを書き換えてコンパイルし直す ・コンパイル時にコンパイラがマルチスレッドで動作するオプションを使う(対応しているもののみ) ・その他 ところで、「プリエンプティブなマルチコアになる」って何? 「マルチスレッドでコンパイルする」「メッセージループがスレッドになる」に続いて またまた第三者からは理解不能な言葉が出て来てるんですけど。
683 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 05:37:36 ] >>680 これは釣りだろ
684 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 06:45:01 ] 「マルチスレッドでコンパイルする」 そういえばVS2005から並行コンパイルができるようになったけど そのことかな。
685 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 08:03:25 ] >>683 知ってる単語を並べただけと言う疑惑も捨てがたい。(w
686 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 10:57:32 ] データを完全にシーケンシャルに 処理する必要があるのに スレッドの接続形態が 1-N-1って場合って どんな利点があるの?キュー作っても処理遅くなるだけじゃね?
687 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 11:26:27 ] メッセージの元になるイベントは、システム全体に対して非同期に起こるんだよ。 おまいのアプリ上だけじゃないし、処理終了を待って定期的に起こるわけでもない。
688 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 14:20:25 ] マルチスレッドでコンパイルする=MTsafeにするだろう
689 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 15:24:34 ] >>686 ここの人には「完全にシーケンシャル」の意味するところがわからないから、 その形態作った奴に聞いてみればいいんじゃね。
690 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 17:14:57 ] よくわからないけど、入力1、処理N、出力1みたいな感じだとすると、 最後の1を遊ばせないためには良いんじゃないかという気がする。 まあ何やるか次第だけど。
691 名前:デフォルトの名無しさん mailto:sage [2008/05/05(月) 17:16:08 ] >>690 でもめちゃくちゃ排他制御かからないかなぁ? 常にシーケンシャルってことは前のデータ待って 処理しないといけないってことだろうし
692 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 11:17:48 ] コンパイラオプションのシングルとMTが具体的に何をしてるのかは知らないが MTにした時に各イベントは完全に非同期で発生する 並列実行してるのだと思ってるのだが違うのか?
693 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 11:46:10 ] いいえ。イベント発生は非同期ですが、受信が並列に行われる保証はありません。 # つーか、並列実行できるくらいならイベント機構はもっと簡略化できるわけで。
694 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 13:47:11 ] >コンパイラオプションのシングルとMTが具体的に何をしてるのかは知らないが コンパイラのヘルプ読めよ・・・
695 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 17:24:03 ] マルチスレッドでコンパイルといえばマルチスレッド実行されるのが当然だろ 何言ってるんだか
696 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 21:18:32 ] ・マルチスレッド (対応のコンパイラ) でコンパイルといえば (コンパイラが) マルチスレッド実行... ・マルチスレッド (オプションをつけた状態) でコンパイルといえば (生成されたプログラムが) マルチスレッド実行... 日本語難しいアルネ。
697 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 22:05:44 ] 最近のコンパイラはマルチスレッドで動作するプログラムを勝手に生成してくれるの?
698 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 22:07:56 ] MT対応ライブラリをリンクするだけじゃね OpenMPとか一応あるけど明示的にディレクティブを書かないといけないし
699 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 22:13:13 ] それはライブラリの使い方次第だろう。 MT-safeになるだけっていうのとはまた違うし。 なんかレベルがよく分からない抽象的な話しかないのは気のせいか。
700 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 22:27:00 ] >>697 コンパイラ自体は何もしないけど MFCとかのフレームワークがするんでしょ
701 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 22:32:49 ] 私はいつものようにMFCでプログラムを組んでいた 当然のごとくMTをコンパイラオプションに指定した ある日、子ウィンドウから親ウィンドウにある関数を実行する必要性が出てきた 私はPostMessageでオリジナルのイベントを実装することを思いついた そこには処理Aと処理Bという2つの関数が存在した 処理Bは処理Aの結果を利用するものである 処理B単体で実行する場合もあるのでこの2つは独立していた 私は当然のごとく各イベントはシーケンスに処理させるのだと思い込んでいた メッセージA、メッセージBと順番に親ウィンドウに送信する するとどうだろうか プログラムは例外エラーを発生させて画面から消えるではないか 私は挙動を調べるべく調査に乗り出した そしてついにその原因を突き止めた この2つの処理は同時に実行されている
702 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 22:42:19 ] 非同期のPostMessageじゃなくて同期のSendMessageだったっけ、そういうのなかった? winapiから遠ざかりすぎてワスレタ。非同期メッセージ通信なのだから、 >各イベントはシーケンスに処理させる って前提は、キューに入れられた順番はあるけど cpuが空いていればキューから取り出してすぐに実行されるってこと?
703 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 23:01:41 ] 内部的にSendMessage使ってる関数でデッドロックしたことがあるのでマルチスレッド怖い
704 名前:デフォルトの名無しさん mailto:sage [2008/05/07(水) 23:05:04 ] デッドロックはアナライザで一発で見つかるから楽。 問題はコンディションレースだ。
705 名前:デフォルトの名無しさん mailto:sage [2008/05/08(木) 09:27:46 ] >>701 MFCをコンパイルするときは/MLオプションを 受け付けなかったと思ったがどうだっただろう。 /MD と /MTの切り替えは問題なく出来るはず。 さらにVS2005からは/MLは廃止になっている。 一応説明しておくと /MLはシングルスレッド用CRTライブラリのスタティックリンク /MTはマルチスレッド用CRTライブラリのスタティックリンク /MDはMSVCRT.DLL(版によって名称の差異あり)へのダイナミックリンク
706 名前:デフォルトの名無しさん mailto:sage [2008/05/08(木) 11:54:00 ] メッセージキューは必要に応じてスレッドごとに生成される。 自他スレッドやOSから発行されるウインドウメッセージはメッセージキューで並列化され、 メッセージループで読み出されることによってその後のウインドウプロシージャの処理は メッセージループのスレッドで実行される。 つまりマルチなのはキューまでで後は単一のスレッドで実行される。 ただし単純にシーケンシャルに実行されるわけではない。 キューはプライオリティキューであり順番が入れ替わることがある。 ウインドウプロシージャ内でメッセージキューに関係する命令を使った場合、 現在のメッセージの処理を一旦中断し別のメッセージに実行権を譲渡することがある。 >>701 はこの辺を並列で実行されたと誤認してるものと思われる。 どうしてもマルチで動作してると言い張るつもりなら、 ウインドウプロシージャにスレッドIDの変化を調べるルーティンを入れて 変化が認められるか調べるのが一番だと思う。
707 名前:デフォルトの名無しさん mailto:sage [2008/05/08(木) 12:34:36 ] >>706 2行目訂正 誤)メッセージキューで並列化され 正)メッセージキューで直列化され
708 名前:デフォルトの名無しさん mailto:sage [2008/05/08(木) 12:41:26 ] >>701 新しいスレッドを作らない限り同時に実行は無いよ。もっとよく調べてみよう。
709 名前:デフォルトの名無しさん mailto:sage [2008/05/08(木) 13:18:51 ] WndProcがマルチスレッドに動くなら そこらじゅうMutexやらCritical Sessionだらけになる予感 もちろんVolatile論争もこのスレ的にOK
710 名前:デフォルトの名無しさん mailto:sage [2008/05/09(金) 15:43:52 ] 同期コストで逆に遅くなりそうだな。
711 名前:デフォルトの名無しさん mailto:sage [2008/05/11(日) 21:24:19 ] どうせCSocketみたいな内部でPeekMessageで回してるのを見て 同時実行されてると思い込んでるだけでしょ。
712 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 20:18:26 ] 何の技術もないんですが、気になってることを質問させてください。 マルチコアプロセッサでマルチスレッドのプログラミングをする時って スレッドを、ポンポンって作って、後はOSとかが暇にしてるコアに 仕事を割り振ってるんですか? それとも、プログラムの側で、「この処理はお前がやれ」ってマルチコアの 特定のコアに指定して割り振るんですか? 調べてみたら、どうも前者っぽいんですが、気になって昨夜は2時間くらい 布団の中で寝れませんでした。お願いします、教えてください。
713 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 20:25:47 ] >>712 何も指定しなければOSが自動的に割り振る。 指定すれば割り振ることができる。 だからどっちともいえる。
714 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 20:31:19 ] >>713 ありがとう。これで今夜はゆっくり寝れる。 もうひとつ聞きたいこと出てきました。 指定する場合ってどうやるのか、キーワードだけでも 教えていただけると有り難いです。
715 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 21:06:27 ] affinityでググればいいんじゃね www.linux.or.jp/JM/html/LDP_man-pages/man2/sched_getaffinity.2.html こんなんとか msdn.microsoft.com/ja-jp/library/cc429346.aspx
716 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 21:15:44 ] >>715 あーりーがーとー。 いろんなキーワードで調べてたけど ずっと見つからなかったものが、ようやく見つかった。 感謝します。 お邪魔しました。
717 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 22:40:13 ] >>716 Linuxだとtasksetってコマンドで簡単に設定できるので便利。
718 名前:デフォルトの名無しさん mailto:sage [2008/05/13(火) 23:52:00 ] >>717 おぉ。寝る前に念のためにきてみたら、またいいこと知った。 ありがとねー。
719 名前:デフォルトの名無しさん [2008/05/21(水) 17:41:08 ] 質問させて下さい。 WindowsでGUIから何らかのアクションでスレッドを起動し、 ESCキーを押下でメッセージボックスを表示して、 スレッドの実行を中止できるようにしたいと考えています。 こんな風に↓ case IDM_KEY_ESCAPE: { if (thread.suspend()==0) { if (MessageBox(hwnd, "", ""),MB_OKCANCEL)==IDOK) { thread.terminate(); } else { thread.resume(); } } break; } で、以下のようなスレッドクラスを作成しました。 (つづきます)
720 名前:719 [2008/05/21(水) 17:42:31 ] class Thread { HANDLE hthread_; unsigned int id_; void run(void) { /* 具体的な処理 */ } public: void start(void) { hthread_ = (HANDLE)_beginthreadex(NULL, 0, Thread::entrypoint, this, 0, &id_); } DWORD suspend(void) const { return SuspendThread(handle()); } DWORD resume(void) const { return ResumeThread(handle())); } static unsigned int WINAPI entrypoint(void* instance) { thread_t* p = static_cast<thread_t*>(instance); p->run(); _endthreadex(0); CloseHandle(p->handle()); p->hthread_ = 0; return 0; } };
721 名前:719 [2008/05/21(水) 17:43:00 ] しかし、実際に使ってみたところ、ESCキーでメッセージボックスを表示すると、 たしかにスレッドの処理は中断するのですが、 タスクマネージャを見ると中断している間も実行メモリが数KBずつ増えていくのです。 それで中断したまま(メッセージボックスを表示したまま)しばらく放っておくと、 タスクマネージャに表示された該当プロセスのスレッド数が1つ減ります。 (つまりGUI起動時のスレッド数になる) そこでメッセージボックスのOKを選択してスレッドを終了すると、 さらにスレッド数が1つ減って、壊れた振る舞いをするという具合です。 とりあえずスレッドクラスについて質問したいのですが、 ↑は変な実装ではないでしょうか?それから使い方も問題ないでしょうか? OS:Windows Vista x64 言語:C++ 環境:Visual Studio 2008
722 名前:719 mailto:sage [2008/05/21(水) 17:46:25 ] すみません。>>720 のthread_tはThreadの間違い、 p->handle()はp->hthread_、それからterminateメソッドが抜けていました。 void terminate(void) { TerminateThread(hthread_, 0); CloseHandle(hthread_); hthread_ = 0; } }
723 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 18:09:32 ] TerminateThreadで終わらせたとき、run内で動的に確保されていたリソースはどうなるでしょうか。 それと、entrypoint内_endthreadex(0)の後に記述した処理は実行されないと思うのですが。 あとは知らん。
724 名前:719 mailto:sage [2008/05/21(水) 18:18:12 ] >>723 どうも。_endthread(0)でスレッドを終了したら、 自動的にentrypointから抜けてしまうのでしょうか?この辺、自信ありません。 (entrypointから抜けるときに_endthreadが呼ばれるというのはMSDNに書いてありましたが…) あとrun内でのメモリの確保は全部boost::shared_ptrを使ってるので問題ないと思います。 いずれにしてもsuspend中に問題が発生しているわけで…。
725 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 18:25:16 ] mallocの中でsuspendしたら・・・とか思うと怖いな 何が起きても不思議ではない気がする
726 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 18:50:00 ] >>722 TerminateThreadの説明読んだ? こんなおっかねーAPI俺は使ったことないぞ。 強制終了に相当する処理だよ。後始末なんか何もしない。
727 名前:719 mailto:sage [2008/05/21(水) 18:59:04 ] TerminateThreadが危険というのは知識としては知ってますが、 そこに至る前のSuspendThreadの時点で問題が起きているようです。 仮にメッセージボックスでキャンセルを選んで、 TerminateThreadではなくResumeThreadを呼んだ場合でも処理が壊れるのです…。
728 名前:719 mailto:sage [2008/05/21(水) 19:03:28 ] >>725 スレッド内で動的にメモリを確保するのは一般的なことだと思うのですが、 その場合にSuspendThreadを呼ぶタイミングが問題になるなら、 Suspend/ResumeThreadというのはものすごく使いにくい関数な気が。
729 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 19:04:04 ] TerminateThread()とか_endthreadex()は、 「呼ばれたらスコープを抜けてローカル変数の解体処理をして…」 なんてことは、一 切 や っ て く れ ま せ ん 。 稼動中のPCの電源を無造作に切るかのようにスレッドの処理を打ち切ってくれます。 shared_ptrのデストラクタなんか呼ばれるわけが無いので、メモリリーク必至です。 で、知っているくせに何でそんなふざけたコード書いてんの?
730 名前:719 mailto:sage [2008/05/21(水) 19:08:11 ] >>729 あ、デストラクタも呼ばれないんですか。それは知りませんでした。勉強になりました。 で、なんでこういうコードを書いているかというと、 危険だというTerminateThreadを何に置き換えるかは後で考えるとして、 とりあえずSuspend/Resumeの部分を実装するために書いたコードなわけで。
731 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 19:11:12 ] >>728 そーだよ。 例えばクリティカルセクションに入ったまま止めてしまったら、再開させるまで他のスレッド入れなくなるわけだし。 あと、これ。 msdn.microsoft.com/en-us/library/ms686345 (VS.85).aspx >This function is primarily designed for use by debuggers. >It is not intended to be used for thread synchronization.
732 名前:719 mailto:sage [2008/05/21(水) 19:19:42 ] >>731 なるほど。その"This function is ..."の1文でいろいろ吹っ切れた気が…。 Suspend/Resumeの機能を実装したければ、外からスレッドに何かシグナルを送って、 スレッド自らの手でSuspendする必要があるわけですね。 SuspendThreadはその部分をよきに計らってくれるものだと勘違いしていました。 どうもありがとう〜。
733 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 19:32:28 ] まあ精進してちょ。
734 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 21:23:54 ] ふつーはイベントを待つ。
735 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 07:53:30 ] グローバルにスレッド管理用のフラグを用意する スレッド起動時にこのフラグを1にセット スレッド内で定期的にこのフラグを監視し0になったら途中で終了する メッセージボックスでキャンセルされた時はこのフラグを0にするだけ
736 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 08:00:05 ] マルチスレッドだとスタック領域が別になるから グローバルで取ったフラグ用変数のポインタをスレッドに最初に渡すのだよ
737 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 08:02:38 ] 別にクラス内のローカルな変数でもいいんだけどね その時はクラスのポインタを渡すのだよ クラス定義を組み込むのを忘れないでね
738 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 10:51:14 ] あとvolatileも
739 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 11:47:42 ] c/c++のvolatileはいろいろあるから、 ちゃんとmutexなどの同期オブジェクトを使うことをすすめる。 ただwindows限定ならvolatileにメモリバリアの意味があるのだっけ?
740 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 13:03:14 ] > c/c++のvolatileはいろいろあるから、 > ちゃんとmutexなどの同期オブジェクトを使うことをすすめる。 もしかして volatile 変数で同期とろうとか思ってる?
741 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 13:08:25 ] 荒れる予感
742 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 13:10:20 ] >>739 メモリバリアの意味はない。 ただ、IA32はコヒーレントキャッシュだから、volatileだけでも 大して問題がないだけ。
743 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 13:18:53 ] ていうかこのケースは知らないが もし「ループを一周余分に回すことになっても問題ない」という 厳密な同期が必要ないものならば、volatileで済むケースはある。 そんなに多くは無いが。
744 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 13:34:51 ] >もし「ループを一周余分に回すことになっても問題ない」という >厳密な同期が必要ないものならば、volatileで済むケースはある。 むしろ今回のケースでは一周分余分に回すのがアウトという状況が考えにくい。
745 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 14:46:29 ] 一周分余分に回ってアウトなら最初から排他なりセマフォなり入れるしな
746 名前:719 mailto:sage [2008/05/25(日) 16:06:04 ] 結局↓のようなクラスにしました。今のところ問題ありません。 class Thread { HANDLE hthread_, hevent_; unsigned int id_; bool cancel_; void run(void) { while (1) { /* 具体的な処理 */ if (cancel_check()) { return; } } } public: Thread(void) : hevent_(CreateEvent(NULL, TRUE, TRUE, NULL)), cancel_(false) {} ~Thread() { CloseHandle(hevent_); } void start(void) { hthread_ = (HANDLE)_beginthreadex(NULL, 0, Thread::entrypoint, this, 0, &id_); } void cancel(void) { cancel_ = true; SetEvent(hevent_); } void suspend(void) { ResetEvent(hevent_); } void resume(void) { SetEvent(hevent_); } bool cancel_check(void) { if (cancel_) { cancel_ = false; return true; } WaitForSingleObject(hevent_, INFINITE); return false; } static unsigned int WINAPI entrypoint(void* instance) { thread_t* p = static_cast<thread_t*>(instance); p->run(); CloseHandle(p->hthread_); p->hthread_ = 0; return 0; } };
747 名前:デフォルトの名無しさん mailto:sage [2008/05/25(日) 16:37:42 ] run()内で例外投げられたらまずくね
748 名前:デフォルトの名無しさん mailto:sage [2008/05/26(月) 03:02:25 ] >>742 ダウト
749 名前:デフォルトの名無しさん mailto:sage [2008/05/26(月) 03:25:49 ] kwsk
750 名前:デフォルトの名無しさん mailto:sage [2008/05/26(月) 03:27:13 ] OoOの問題じゃないかなと思ったり。
751 名前:デフォルトの名無しさん mailto:sage [2008/05/26(月) 13:30:52 ] UOがどうしたって?
752 名前:匿名 [2008/05/30(金) 15:12:16 ] スレッドは非常に難しいです。 スレッドを利用しないでコンカレントプログラムが容易にできます。 以下のページが参考になります。 www.cspjapan.org/
753 名前:デフォルトの名無しさん mailto:sage [2008/05/30(金) 15:57:17 ] ばか?
754 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 15:10:05 ] 生成したスレッドがmallocをしている最中に SuspendThreadするとどんな問題が発生しますか?
755 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 15:26:07 ] mallocの中で排他制御しているだろうから、他のスレッドがmallocを呼 ぶと返ってこなくなるかも。
756 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 15:27:38 ] mallocがマルチスレッド対応版だと仮定すると、 ヒープ管理データへのアクセスの排他のために mutexを握るタイミングがあるはず そのタイミングでSuspendされると ほかのスレッドがmalloc/free関連の処理をしようとして mutex握れなくてずっと待ちに入る newがmallocをベースにしているならnew/deleteも はたから見るとハングアップに見える
757 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 22:23:21 ] >739 C#のvolatileはメモリバリアの意味もあるよ。 C/C++じゃないよ。
758 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 22:32:43 ] ふ〜ん
759 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 21:41:57 ] MSDNのSystem.Threading.Thread.MemoryBarrierの説明が微妙でわかりづらい >MemoryBarrier は、複数の Intel Itanium プロセッサを使用しているシステムなど、 >ウィーク メモリ オーダリングを採用したマルチプロセッサ システムでだけ使用します。
760 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 23:24:59 ] memory orderingの知識がないだけじゃね? strong memory orderingのx86では不要。 シングルプロセッサ(1コア)のシステムでも不要。 weak memory orderingのItaniumを複数使ったシステムでは必要。 書いてあるとおりw memory orderingはこれでも読んどけ ttp://www.arch.ce.hiroshima-cu.ac.jp/~kitamura/public/architecture_2003_13.pdf x86はSPARCのTSOと、ItniumはSPARCのRMOと同じはず
761 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 00:21:36 ] 質問しようと思ったら>>746 に俺が・・・ この場合だとentrypoint内でCloseHandleしてreturn完了後にendthreadex呼ばれるという 挙動であってるのかな?で、ハンドルも問題なく閉じられるのか?
762 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 05:09:09 ] >>746 は無茶苦茶だろ。 とりあえず思ったこと。 ・startで生成したhthreadを別のスレッドでcloseするのが変。 代入前にサブスレッドが終了したらアウチ ・startが2回呼び出されたときのガードは当然してるよな ・とりあえずcancel_はvolatileにしとけ。即座でなくても そのうちtrueが伝わるだろう ・cancelは変数で一時停止がEventだが、どちらかに統一しとけ ・entrypointはprivateにしとけ ・entrypintでrunの例外処理しないとendthreadexが呼ばれない ・キャストはreinterpret_cast使え ・サブスレッドの実行を管理するThreadとサブスレッド処理のクラスを どうして同じにするかな。runとcancel_checkはThreadと別クラスに分離した 方がよいと思う ・_beginthreadexとCreateEventのエラーチェックしろ ・サブスレッドが完了したか調べる関数がほしい あと、Threadがスコープから抜けるとrunのthisが無効になる設計は嫌いだ。 Threadのデストラクタでjoin(WaitForSingleObject(hthread_))すべきだと思う。 呼び出し側が責任を持って事前にcancelを呼び出し、それを怠ったら 不正メモリアクセスでなく永久waitになった方がマシ
763 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 12:08:58 ] 761ですが・・・俺の場合は ・コンストラクタで生成してるけどサスペンドで作成してるから、代入前に終了はないはず ・bool使ってやってます。全体的にこれらの操作はミューテックスで排他してるんですが、 それで十分なんでしょうか? ・ ・ ・なってます ・なるほどやりました。 ・なるほどやりました。 ・実行管理がThreadクラスで、サブ処理がRunnableインタフェースを被ったクラスのrun()メソッド です。Thread自身もRunnableインタフェースを継承してます。(ただしrun()は空) ・失敗してたら何もしないようにしただけです・・・ ・void Thread::join(DWORD timeout){ if(tb == NULL)return; ::WaitForSingleObject(tb->hThread,timeout); } これで十分でしょうか?
764 名前:デフォルトの名無しさん [2008/06/08(日) 13:05:59 ] MSが言っている"アラート可能な待機状態"とはどういう状態のことですか?
765 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 13:08:55 ] 何らかのイベント?とかで待機を中断できるってことじゃね?
766 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 13:11:25 ] 746みたいな事をやるときのboost::threadの楽さと言ったら…。