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】 【言語】 【実行環境】 【その他突起する事項】
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の楽さと言ったら…。
767 名前:デフォルトの名無しさん [2008/06/08(日) 13:12:39 ] それは、普通の待機状態とアラート可能な待機状態の違いは スレッドプロセスが__cdeclか__stdcallかの違いである ということですか?
768 名前:デフォルトの名無しさん [2008/06/08(日) 13:24:31 ] 違いますね。APCとか理解できません。
769 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 13:55:21 ] >>764 重複I/Oを使うときにのイベント待機に使う。
770 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 19:17:36 ] >764 SleepExとかWaitFor〜Exで、bAlertable=TRUEの状態で寝てるとき
771 名前:762です mailto:sage [2008/06/09(月) 00:32:13 ] >>763 > ・コンストラクタで生成してるけどサスペンドで作成 → 論理的に正しく動くのはわかったけど、わかりづらくない? ハンドル作成したスレッドが(デストラクタあたりで)closeするのが自然だと思うんだが。 > ・bool使ってやってます。全体的にこれらの操作はミューテックスで排他してるんですが、 → startの多重チェックに同期は要らない。なぜならstartは 一つのスレッド(メイン)からしか呼び出さないのが前提だから > Thread自身もRunnableインタフェースを継承してます それはJava APIと同じ設計だけど、APIの設計ミスだと思う。 各クラスの役割は最低限にしようよ。 Runnable: サブスレッドで実行する処理のクラス(主にサブスレッドで使用) Thread: Runnableのスレッド実行を管理するクラス(メインスレッドから使用) 実行制御でもcancel/suspend/resumeは処理固有なのでRunnable側に実装。 スレッドハンドルはスレッド実行管理の話だからThreadでclose。 > void Thread::join(DWORD timeout) できれば戻り値をboolにして DWORD status = ::WaitForSingleObject(?????) if (status == WAIT_ABANDONED) throw ????; return status == WAIT_OBJECT_0; // 完了したかどうか かな。
772 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 02:04:45 ] JavaのThreadにケチつけるアホがいるスレはここですか?
773 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 02:17:36 ] JavaのThread implements Runnableは失敗だろjk
774 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 18:16:32 ] Treadクラスの継承が失敗だろ
775 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 23:04:19 ] 761です。もう全然うまくいかないので、なんか言ってもらうために スレッド周辺のプログラムをアップしてみます・・・。include "common.h"は消していいです お願いします>< ttp://ccfa.info/cgi-bin/up/src/up20166.zip
776 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 23:06:31 ] よし、何か言ってやる。 >>775 がんばれ!
777 名前:デフォルトの名無しさん mailto:sage [2008/06/10(火) 01:28:22 ] >>775 ○Mutex ・LockでWaitForSingleObjectの戻り値確認しろ。タイムアウトしたら大変なことになるぞ ○Thread ・何でthread_bodyの定義を書く前に変数宣言できるんだ?コンパイル通った? thread_bodyのスマートポインタでないとマズくね? ・start内に例外発生するとマズい場所が多すぎ。line 60,61,62,63,64,68 ・isAliveのロジックが間違ってる。スレッドがSTILL_ACTIVE返したら区別つかない。 WaitForSingleObject(スレッドハンドル) == WAIT_OBJECT_0 で判断しろ ・ThreadProcで(const Thread&)のキャストは要らないでしょ ・マップ操作前後のロックタイミングはこれでいいと思う ・suspend/resumeのロックはこれでいいと思う ・joinでWaitForSingleObjectの戻り値確認して ・isAliveにロックは不要 ・クラス設計が変。currentThreadの返したThreadは何だ? 実際のrunと関係ないrunを持つThreadをnewして返すのは絶対変だ ・Runnableとt_threadの使い分けをもう少し整理して ・ヘッダ名見直せ。<cstdio><windows.h><process.h><map><cstdio><sstream> > tb=thread_pool_for_runnable[target];//既にあるRunnableの時はそれを使う ? エラー返すべきでは? あと、ミューテックスのロックはヘルパークラス作れ。 コンストラクタでミューテックスを受け取ってロックし、デストラクタでアンロック。 でないと途中で例外が発生したときにいちいち対処できない。 > もう全然うまくいかないので 何がうまくいかない? 何となく動きそうだが。 コンパイルエラーとか言ったら殺
778 名前:デフォルトの名無しさん mailto:sage [2008/06/10(火) 07:15:40 ] 今携帯なんで、後で詳しく見ますが、うまくいかないというのは これで画像読み込みをしたときに画像読み込みが出来なかったりするんです 実験中には終了時に不正アクセスみたいのが出たり…
779 名前:デフォルトの名無しさん mailto:sage [2008/06/10(火) 14:38:51 ] 777が優しすぎる 俺が男なら惚れてたね
780 名前:デフォルトの名無しさん mailto:sage [2008/06/10(火) 14:56:56 ] 俺は男だから惚れた
781 名前:デフォルトの名無しさん mailto:sage [2008/06/10(火) 16:38:37 ] じゃあ掘れるのか
782 名前:デフォルトの名無しさん mailto:sage [2008/06/10(火) 19:43:21 ] 惚れたけど掘れない。
783 名前:719 mailto:sage [2008/06/10(火) 20:22:05 ] いやぁ、勉強になるなぁ…。
784 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 07:10:26 ] 質問があります pthreadでは途中でスレッドをキャンセルする場合 pthread_cancelを遅延キャンセルでコールして、 クリーンナップハンドラでリソースを開放するという方法が考えられますが、 C++では実行環境(gcc,glibc)によって、クリーンナップ内でオブジェクトの デストラクタが呼ばれなかったり、例外処理が行われないなどといったことがあるみたいですが、 「C++ではこのようにしてpthreadを中段させるべき」といった 定石的手法が確立しているのでしょうか? できればURIなど情報源などもあれば教えてください。 【OS】 Linux2.6 【言語】 C++ 【実行環境】 RHEL5(pthread) 【その他突起する事項】 「RHEL5の中のライブラリならサポートしてるので気にするな」ってのは無しで
785 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 07:47:54 ] 外から中断なんかしない。 当たり前すぎて泣けてくる。
786 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 12:24:11 ] >>784 安全に中断させる方法なんて存在しない。 だが、スレッドのエントリ関数のreturnを実行して正しく終了させる方法はいくらでもある。
787 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 13:55:11 ] > 「C++ではこのようにしてpthreadを中段させるべき」といった > 定石的手法が確立しているのでしょうか? 中断通知機構は自分で独自に実装。必ずエントリポイントの関数まで 戻るようにする。 異常時に終了するため、終了用の例外クラスを作成。エントリポイントのみ でcatchし、他はクラスに対し例外中立なコードを書く。 ソースは俺。
788 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 14:04:26 ] >>778 joinせずに終了したか、Thread,Runnableのメモリが誤って解放されたのでは
789 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 20:40:04 ] スレッド止めてプロセスにする
790 名前:777 mailto:sage [2008/06/11(水) 21:51:22 ] >>775 GetLastErrorの戻り値判定ロジックが逆。 細かい間違いは修正したが普通に動いた。元のろだ?のup方法がわからなかったので↓にup www11.axfc.net/uploader/He/so/108823.zip DLパスは mt さすがにmy_ptrとかいうのはboost::shared_ptrに置き換えさせてもらった。
791 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 22:28:58 ] アクターモデルって奴の C++とかjavaとかでのサンプルない?
792 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 22:36:55 ] 761です >>790 ブワッ!なんと言うやさしさ・・・やっと時間が取れたので、777を元に修正してたら、なんという でも俺はウホじゃないです。すいません (const Thread&)のキャストですが、こうしたらローカル変数の寿命がどうたらで1個分生成・破棄の コストが浮くかなあと思って付けたんですが・・・まぁ、確認もせずにつけたので効果はいざ知れず > currentThreadの返したThreadは何だ? この関数を実行したスレッドがスレッドプール内に存在すれば、そのスレッドを操作する Threadオブジェクトを返します。 既存のRunnableの時再利用するのは Hoge(){ Thread th(this);th.start(); } ~Hoge(){ Thread(this).join(); } とすることに憧れていたからです・・・。つまり俺がちょっとおかしいのです
793 名前:デフォルトの名無しさん mailto:sage [2008/06/11(水) 23:27:08 ] pthread mutexで 読みスレッドが2人 書きスレッドが2人 といる場合、rwlock使うと読んでる間に 書き込もうとしてもロックされる?
794 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 00:24:12 ] pthreadは知らないけど一般のReader-Writer-Lockなら排他制御されなぎまずいんじゃね。 Readerのみの場合に排他されないんだと思う。 Reader vs. Reader → 排他されない Reader vs. Writer → 排他される Writer vs. Writer → 排他される
795 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 00:38:59 ] Pthreadもそうだったと思う Man読みゃいいんだけどね
796 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 01:47:42 ] スレッドAがrdlockする スレッドBがwrlockしようとする(が、rdlock中なのでブロック) この状態の時に、スレッドCがrdlockしようとすると 1.スレッドCがrdlockを取得(Aと共存)出来る 2.スレッドB(ロック獲得優先権がある)の処理終了までブロックする 一般的にはどうなる? ・一般的に、rwlockと呼ばれるものの動作として決まっている(どっち?) ・pthreadの標準として決まっている(どっち?) ・何も決まってない(実装依存)
797 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 01:54:39 ] >>796 opengroup.org/onlinepubs/007908775/xsh/pthread_rwlock_rdlock.html > It is unspecified whether the calling thread acquires the lock > when a writer does not hold the lock and there are writers waiting for the lock. 何も決まってないぽい
798 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 02:00:50 ] おー、thx