マルチスレッドプログ ..
649:デフォルトの名無しさん
08/05/02 17:43:24
自作板にいるキチガイです。シングルスレッドで作成されてるソフトが
カーネルによってマルチコアにスレッド(タスクのことか?)が分散されると申しております。
このIDだけの発言では分かりにくいが、このスレにはシングルスレッドでもマルチコアのほうが早いと
のたまわってるキチガイがいます。
まだまだシングルCPUで頑張る人集合
スレリンク(jisaku板)
800 Socket774 sage New! 2008/05/02(金) 08:31:32 ID:Aaj/7HlH
このスレのシングルコアユーザーは未だにWindows3.1を使ってるようだw
801 Socket774 sage New! 2008/05/02(金) 08:32:49 ID:Aaj/7HlH
プログラムのスレッドと
CPUが処理する単位のスレッドは
意味が違うw
802 Socket774 sage New! 2008/05/02(金) 08:42:42 ID:Aaj/7HlH
プログラムのスレッドはカーネルによってさらに細分化される
与えられたCPUタイムによってそれを1つづつ実行していく
大まかに2ブロックに分割されたとしよう
1コアが1ブロックを実行してCPU使用権が終了する
その時に2コアが暇をしてるので2ブロックに即座に使用権が渡される
つまり単純に2倍の処理性能になる
806 Socket774 sage New! 2008/05/02(金) 10:52:29 ID:Aaj/7HlH
いやだからマルチスレッドOSって時点で
実際のCPU利用率は半分以下なんだよ
どんだけがんばってもそうなの
シングルコアだったら100%使えるとかないからw
コアが2になるとより100%に近い状態になるわけ
一般に1.8倍だと言われる
MS-DOSやWindows3.1を使ってる人はシングルコアのが早いかもねwww
807 Socket774 sage New! 2008/05/02(金) 10:57:04 ID:Aaj/7HlH
>>803
ベンチマークのような単純処理の繰り返しではスレッドの細分化はほとんど行われない
ゲームみたいな大きなスレッドになると実際に4倍近くの性能を発揮する
650:デフォルトの名無しさん
08/05/02 17:51:33
>>649
頭のおかしな人というのはある程度の確率で常にあらわれるものであって、
そういう人がいるのはおかしいとか、説明して頭をよくしてあげよう等の考えは
全くの無駄だと思う。中身の入って無い枝豆同様ハズレとして無視するよりない。
いらいらする気持はわかるけどね。
651:デフォルトの名無しさん
08/05/02 17:52:33
コピペ君に応答する奴も馬鹿だな、まで読んだ。
652:デフォルトの名無しさん
08/05/02 19:14:41
osのタスク切り替え戦略によってはそうなるかもしれないけど、
普通は強制的な一定タイムスライスじゃないよね。
システムコール待つのにビジーウェイトでもしてると思ってんのか。
653:デフォルトの名無しさん
08/05/02 20:14:27
ほかのタスクや割り込み処理に割り込まれる可能性が減る(ほかのCPUに割り振られる)から
「遅くなりにくい」ということはいえるが
速くなることはないだろうなあ。
って件のスレで当人書いてるじゃん
654:デフォルトの名無しさん
08/05/02 21:56:31
1coreの時にOS側のタスクによるオーバヘッドが1%程度あったとすると
2coreならアプリの実行時間が1%短くなる程度なら有り得る
655:デフォルトの名無しさん
08/05/03 06:58:19
ゲームでならDirectSoundは別スレッドで動いてるので
もうちょっと効果あるかもね。
656:デフォルトの名無しさん
08/05/03 08:29:25
例えばX11だと描画はサーバプロセスが行なうから結構効果がありますね。
でもそれをシングルスレッドアプリが速くなると言ってしまうとちょっと違うと思いますが。
657:デフォルトの名無しさん
08/05/03 08:33:56
よっぽど単純なプログラムでもない限り
完全なシングルスレッドなんてあり得ないんですけどねw
658:デフォルトの名無しさん
08/05/03 08:40:56
たとえばEXCELで
再計算処理が行われてる時にメニューを実行すると
再計算、描画、メニューの3つのスレッドが形成される
659:デフォルトの名無しさん
08/05/03 08:47:38
ビス太のユーザーランドスレッドの方針を分かって話してるの?
660:デフォルトの名無しさん
08/05/03 12:26:31
スレッドプールのはなし?
661:デフォルトの名無しさん
08/05/03 15:17:42
>>658
スレッドが生成されるかどうかと
並行実行するかどうかは別だぞ
662:デフォルトの名無しさん
08/05/03 18:15:41
OpenMP中で使ってるとか
そんなんじゃねーのw
663:デフォルトの名無しさん
08/05/03 19:22:28
>>661
XPでは平行実行してるが?
664:デフォルトの名無しさん
08/05/03 19:59:25
>>663
させるかどうか、だ
665:デフォルトの名無しさん
08/05/03 23:51:43
シングルスレッドでコンパイルするやつはいないだろw
666:デフォルトの名無しさん
08/05/04 00:40:42
それまでの話の流れとは関係ないが
「マルチスレッド対応ライブラリを使用する」と
「マルチスレッドで動作するプログラムにする」は全く違うのだが
まさかとは思うが、>>665はそういう意味じゃないよな?
当然、「コンパイラをマルチスレッドで動作させる」だよね?
一応触れておくと
Win32で普通にGUIプログラムを作る場合、明示的にスレッド関連の操作をしない限り
マルチスレッドで動くことは無い。
何故なら、メッセージキューが1スレッドに1つ作られるので
そこからのイベントで処理を記述する書き方だと、1スレッドにしかならないから。
(イベントハンドラでスレッド操作をすれば当然マルチスレッドも可能)
もちろん、カーネル内の処理(割り込み等)は別。
667:デフォルトの名無しさん
08/05/04 00:59:30
そういえば、Win9xのWinsock2の非同期処理は
内部的にスレッド作って擬似動作させてたんだっけ。
忘れてた。
668:デフォルトの名無しさん
08/05/04 01:14:13
>>666
メッセージキューも明示的に作る(作らせる)ものであって
スレッド作成=メッセージキュー作成じゃないよ。
669:デフォルトの名無しさん
08/05/04 12:10:33
> メッセージキューも明示的に作る(作らせる)ものであって
具体的にどうやって作るの?
670:デフォルトの名無しさん
08/05/04 12:39:33
MSDNのPostThreadMessageの所に書いてあるな
671:まあ、明示的がどうかは人によって違うと思うが...
08/05/04 16:07:57
これのことかな...
> その後、ポスト先のスレッドで、
> PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) を呼び出し、
> このスレッド用のメッセージキューを強制的に作成します。
でもこれって、
> スレッドが Win32 のユーザー関数または GDI 関数のいずれかを最初に
> 呼び出した時点で、システムはそのスレッドのメッセージキューを作成
> します。
ってことだよね。
あまり「明示的」とは思えないんだが...。
672:デフォルトの名無しさん
08/05/04 17:10:13
風が吹いたら桶屋が儲かるくらい暗黙的でなければ明示的
673:デフォルトの名無しさん
08/05/04 22:53:30
いや別にメッセージループに入ったからといって
CPUを最後まで占有出来るわけじゃないのだ
途中で強制的に割り込まれる
そうすると他のループに権利が渡されるだけだな
マルチスレッドでコンパイルすると各メッセージループは完全に独立したスレッドになる
だから既存のアプリもほとんどはデュアルコアの恩恵がある
674:デフォルトの名無しさん
08/05/04 23:11:24
おまえはそんなにメッセージループを作っているのか?
大多数のアプリはWinMainの中のGetMessage1つだけだと思うが
675:デフォルトの名無しさん
08/05/04 23:12:03
それと、「マルチスレッドでコンパイルする」の意味を具体的に説明しろよ
676:デフォルトの名無しさん
08/05/04 23:14:14
上の方は、プリエンプティブマルチタスクの解説で、4行目の
「他のループ」=「他のプロセスのメッセージループ」なのかなー
と思って読んでいたが
>マルチスレッドでコンパイルすると各メッセージループは完全に独立したスレッドになる
え?
677:デフォルトの名無しさん
08/05/05 00:56:45
ちょっぴりエスパー能力を発揮して解読してみた。
普通、「メッセージループ」と言うと
while (GetMessage()) { ... } の部分のことを指すと思うのだが
おそらくこのヒトは、DispatchMessageで間接的に呼ばれるルーチン、
大抵は「WndProcの呼び出し1回」のことを
「メッセージループ」と呼んでいるような気がする。
678:デフォルトの名無しさん
08/05/05 01:18:24
だとしてもウインドウプロシージャがマルチスレッドで
並列実行されたりはしないと思うが。
679:デフォルトの名無しさん
08/05/05 01:48:05
もちろんその通り。
大丈夫、基本的な仕組みを理解してないのは、多分一人だけだから。
680:デフォルトの名無しさん
08/05/05 03:39:24
え? そうなん?
メッセージループをマルチスレッドでコンパイルしたら
完全にプリエンプティブなマルチコアになるでしょ
681:デフォルトの名無しさん
08/05/05 05:18:58
だからその「マルチスレッドでコンパイル」って、何をどうすることなの?
682:デフォルトの名無しさん
08/05/05 05:34:27
一応、>>666の前半部に、候補としていくつか挙げてあるけど
・マルチスレッドライブラリを使用する(コンパイラオプションを設定)
・マルチスレッドで動作するようにソースコードを書き換えてコンパイルし直す
・コンパイル時にコンパイラがマルチスレッドで動作するオプションを使う(対応しているもののみ)
・その他
ところで、「プリエンプティブなマルチコアになる」って何?
「マルチスレッドでコンパイルする」「メッセージループがスレッドになる」に続いて
またまた第三者からは理解不能な言葉が出て来てるんですけど。
683:デフォルトの名無しさん
08/05/05 05:37:36
>>680
これは釣りだろ
684:デフォルトの名無しさん
08/05/05 06:45:01
「マルチスレッドでコンパイルする」
そういえばVS2005から並行コンパイルができるようになったけど
そのことかな。
685:デフォルトの名無しさん
08/05/05 08:03:25
>>683
知ってる単語を並べただけと言う疑惑も捨てがたい。(w
686:デフォルトの名無しさん
08/05/05 10:57:32
データを完全にシーケンシャルに
処理する必要があるのに
スレッドの接続形態が
1-N-1って場合って
どんな利点があるの?キュー作っても処理遅くなるだけじゃね?
687:デフォルトの名無しさん
08/05/05 11:26:27
メッセージの元になるイベントは、システム全体に対して非同期に起こるんだよ。
おまいのアプリ上だけじゃないし、処理終了を待って定期的に起こるわけでもない。
688:デフォルトの名無しさん
08/05/05 14:20:25
マルチスレッドでコンパイルする=MTsafeにするだろう
689:デフォルトの名無しさん
08/05/05 15:24:34
>>686
ここの人には「完全にシーケンシャル」の意味するところがわからないから、
その形態作った奴に聞いてみればいいんじゃね。
690:デフォルトの名無しさん
08/05/05 17:14:57
よくわからないけど、入力1、処理N、出力1みたいな感じだとすると、
最後の1を遊ばせないためには良いんじゃないかという気がする。
まあ何やるか次第だけど。
691:デフォルトの名無しさん
08/05/05 17:16:08
>>690
でもめちゃくちゃ排他制御かからないかなぁ?
常にシーケンシャルってことは前のデータ待って
処理しないといけないってことだろうし
692:デフォルトの名無しさん
08/05/07 11:17:48
コンパイラオプションのシングルとMTが具体的に何をしてるのかは知らないが
MTにした時に各イベントは完全に非同期で発生する
並列実行してるのだと思ってるのだが違うのか?
693:デフォルトの名無しさん
08/05/07 11:46:10
いいえ。イベント発生は非同期ですが、受信が並列に行われる保証はありません。
# つーか、並列実行できるくらいならイベント機構はもっと簡略化できるわけで。
694:デフォルトの名無しさん
08/05/07 13:47:11
>コンパイラオプションのシングルとMTが具体的に何をしてるのかは知らないが
コンパイラのヘルプ読めよ・・・
695:デフォルトの名無しさん
08/05/07 17:24:03
マルチスレッドでコンパイルといえばマルチスレッド実行されるのが当然だろ
何言ってるんだか
696:デフォルトの名無しさん
08/05/07 21:18:32
・マルチスレッド (対応のコンパイラ) でコンパイルといえば
(コンパイラが) マルチスレッド実行...
・マルチスレッド (オプションをつけた状態) でコンパイルといえば
(生成されたプログラムが) マルチスレッド実行...
日本語難しいアルネ。
697:デフォルトの名無しさん
08/05/07 22:05:44
最近のコンパイラはマルチスレッドで動作するプログラムを勝手に生成してくれるの?
698:デフォルトの名無しさん
08/05/07 22:07:56
MT対応ライブラリをリンクするだけじゃね
OpenMPとか一応あるけど明示的にディレクティブを書かないといけないし
699:デフォルトの名無しさん
08/05/07 22:13:13
それはライブラリの使い方次第だろう。
MT-safeになるだけっていうのとはまた違うし。
なんかレベルがよく分からない抽象的な話しかないのは気のせいか。
700:デフォルトの名無しさん
08/05/07 22:27:00
>>697
コンパイラ自体は何もしないけど
MFCとかのフレームワークがするんでしょ
701:デフォルトの名無しさん
08/05/07 22:32:49
私はいつものようにMFCでプログラムを組んでいた
当然のごとくMTをコンパイラオプションに指定した
ある日、子ウィンドウから親ウィンドウにある関数を実行する必要性が出てきた
私はPostMessageでオリジナルのイベントを実装することを思いついた
そこには処理Aと処理Bという2つの関数が存在した
処理Bは処理Aの結果を利用するものである
処理B単体で実行する場合もあるのでこの2つは独立していた
私は当然のごとく各イベントはシーケンスに処理させるのだと思い込んでいた
メッセージA、メッセージBと順番に親ウィンドウに送信する
するとどうだろうか
プログラムは例外エラーを発生させて画面から消えるではないか
私は挙動を調べるべく調査に乗り出した
そしてついにその原因を突き止めた
この2つの処理は同時に実行されている
702:デフォルトの名無しさん
08/05/07 22:42:19
非同期のPostMessageじゃなくて同期のSendMessageだったっけ、そういうのなかった?
winapiから遠ざかりすぎてワスレタ。非同期メッセージ通信なのだから、
>各イベントはシーケンスに処理させる
って前提は、キューに入れられた順番はあるけど
cpuが空いていればキューから取り出してすぐに実行されるってこと?
703:デフォルトの名無しさん
08/05/07 23:01:41
内部的にSendMessage使ってる関数でデッドロックしたことがあるのでマルチスレッド怖い
704:デフォルトの名無しさん
08/05/07 23:05:04
デッドロックはアナライザで一発で見つかるから楽。
問題はコンディションレースだ。
705:デフォルトの名無しさん
08/05/08 09:27:46
>>701
MFCをコンパイルするときは/MLオプションを
受け付けなかったと思ったがどうだっただろう。
/MD と /MTの切り替えは問題なく出来るはず。
さらにVS2005からは/MLは廃止になっている。
一応説明しておくと
/MLはシングルスレッド用CRTライブラリのスタティックリンク
/MTはマルチスレッド用CRTライブラリのスタティックリンク
/MDはMSVCRT.DLL(版によって名称の差異あり)へのダイナミックリンク
706:デフォルトの名無しさん
08/05/08 11:54:00
メッセージキューは必要に応じてスレッドごとに生成される。
自他スレッドやOSから発行されるウインドウメッセージはメッセージキューで並列化され、
メッセージループで読み出されることによってその後のウインドウプロシージャの処理は
メッセージループのスレッドで実行される。
つまりマルチなのはキューまでで後は単一のスレッドで実行される。
ただし単純にシーケンシャルに実行されるわけではない。
キューはプライオリティキューであり順番が入れ替わることがある。
ウインドウプロシージャ内でメッセージキューに関係する命令を使った場合、
現在のメッセージの処理を一旦中断し別のメッセージに実行権を譲渡することがある。
>>701はこの辺を並列で実行されたと誤認してるものと思われる。
どうしてもマルチで動作してると言い張るつもりなら、
ウインドウプロシージャにスレッドIDの変化を調べるルーティンを入れて
変化が認められるか調べるのが一番だと思う。
707:デフォルトの名無しさん
08/05/08 12:34:36
>>706
2行目訂正
誤)メッセージキューで並列化され
正)メッセージキューで直列化され
708:デフォルトの名無しさん
08/05/08 12:41:26
>>701
新しいスレッドを作らない限り同時に実行は無いよ。もっとよく調べてみよう。
709:デフォルトの名無しさん
08/05/08 13:18:51
WndProcがマルチスレッドに動くなら
そこらじゅうMutexやらCritical Sessionだらけになる予感
もちろんVolatile論争もこのスレ的にOK
710:デフォルトの名無しさん
08/05/09 15:43:52
同期コストで逆に遅くなりそうだな。
711:デフォルトの名無しさん
08/05/11 21:24:19
どうせCSocketみたいな内部でPeekMessageで回してるのを見て
同時実行されてると思い込んでるだけでしょ。
712:デフォルトの名無しさん
08/05/13 20:18:26
何の技術もないんですが、気になってることを質問させてください。
マルチコアプロセッサでマルチスレッドのプログラミングをする時って
スレッドを、ポンポンって作って、後はOSとかが暇にしてるコアに
仕事を割り振ってるんですか?
それとも、プログラムの側で、「この処理はお前がやれ」ってマルチコアの
特定のコアに指定して割り振るんですか?
調べてみたら、どうも前者っぽいんですが、気になって昨夜は2時間くらい
布団の中で寝れませんでした。お願いします、教えてください。
713:デフォルトの名無しさん
08/05/13 20:25:47
>>712
何も指定しなければOSが自動的に割り振る。
指定すれば割り振ることができる。
だからどっちともいえる。
714:デフォルトの名無しさん
08/05/13 20:31:19
>>713
ありがとう。これで今夜はゆっくり寝れる。
もうひとつ聞きたいこと出てきました。
指定する場合ってどうやるのか、キーワードだけでも
教えていただけると有り難いです。
715:デフォルトの名無しさん
08/05/13 21:06:27
affinityでググればいいんじゃね
URLリンク(www.linux.or.jp)
こんなんとか
URLリンク(msdn.microsoft.com)
716:デフォルトの名無しさん
08/05/13 21:15:44
>>715
あーりーがーとー。
いろんなキーワードで調べてたけど
ずっと見つからなかったものが、ようやく見つかった。
感謝します。
お邪魔しました。
717:デフォルトの名無しさん
08/05/13 22:40:13
>>716
Linuxだとtasksetってコマンドで簡単に設定できるので便利。
718:デフォルトの名無しさん
08/05/13 23:52:00
>>717
おぉ。寝る前に念のためにきてみたら、またいいこと知った。
ありがとねー。
719:デフォルトの名無しさん
08/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
08/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
08/05/21 17:43:00
しかし、実際に使ってみたところ、ESCキーでメッセージボックスを表示すると、
たしかにスレッドの処理は中断するのですが、
タスクマネージャを見ると中断している間も実行メモリが数KBずつ増えていくのです。
それで中断したまま(メッセージボックスを表示したまま)しばらく放っておくと、
タスクマネージャに表示された該当プロセスのスレッド数が1つ減ります。
(つまりGUI起動時のスレッド数になる)
そこでメッセージボックスのOKを選択してスレッドを終了すると、
さらにスレッド数が1つ減って、壊れた振る舞いをするという具合です。
とりあえずスレッドクラスについて質問したいのですが、
↑は変な実装ではないでしょうか?それから使い方も問題ないでしょうか?
OS:Windows Vista x64
言語:C++
環境:Visual Studio 2008
722:719
08/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:デフォルトの名無しさん
08/05/21 18:09:32
TerminateThreadで終わらせたとき、run内で動的に確保されていたリソースはどうなるでしょうか。
それと、entrypoint内_endthreadex(0)の後に記述した処理は実行されないと思うのですが。
あとは知らん。
724:719
08/05/21 18:18:12
>>723 どうも。_endthread(0)でスレッドを終了したら、
自動的にentrypointから抜けてしまうのでしょうか?この辺、自信ありません。
(entrypointから抜けるときに_endthreadが呼ばれるというのはMSDNに書いてありましたが…)
あとrun内でのメモリの確保は全部boost::shared_ptrを使ってるので問題ないと思います。
いずれにしてもsuspend中に問題が発生しているわけで…。
725:デフォルトの名無しさん
08/05/21 18:25:16
mallocの中でsuspendしたら・・・とか思うと怖いな
何が起きても不思議ではない気がする
726:デフォルトの名無しさん
08/05/21 18:50:00
>>722
TerminateThreadの説明読んだ?
こんなおっかねーAPI俺は使ったことないぞ。
強制終了に相当する処理だよ。後始末なんか何もしない。
727:719
08/05/21 18:59:04
TerminateThreadが危険というのは知識としては知ってますが、
そこに至る前のSuspendThreadの時点で問題が起きているようです。
仮にメッセージボックスでキャンセルを選んで、
TerminateThreadではなくResumeThreadを呼んだ場合でも処理が壊れるのです…。
728:719
08/05/21 19:03:28
>>725
スレッド内で動的にメモリを確保するのは一般的なことだと思うのですが、
その場合にSuspendThreadを呼ぶタイミングが問題になるなら、
Suspend/ResumeThreadというのはものすごく使いにくい関数な気が。
729:デフォルトの名無しさん
08/05/21 19:04:04
TerminateThread()とか_endthreadex()は、
「呼ばれたらスコープを抜けてローカル変数の解体処理をして…」
なんてことは、一 切 や っ て く れ ま せ ん 。
稼動中のPCの電源を無造作に切るかのようにスレッドの処理を打ち切ってくれます。
shared_ptrのデストラクタなんか呼ばれるわけが無いので、メモリリーク必至です。
で、知っているくせに何でそんなふざけたコード書いてんの?
730:719
08/05/21 19:08:11
>>729
あ、デストラクタも呼ばれないんですか。それは知りませんでした。勉強になりました。
で、なんでこういうコードを書いているかというと、
危険だというTerminateThreadを何に置き換えるかは後で考えるとして、
とりあえずSuspend/Resumeの部分を実装するために書いたコードなわけで。
731:デフォルトの名無しさん
08/05/21 19:11:12
>>728
そーだよ。
例えばクリティカルセクションに入ったまま止めてしまったら、再開させるまで他のスレッド入れなくなるわけだし。
あと、これ。
URLリンク(msdn.microsoft.com)(VS.85).aspx
>This function is primarily designed for use by debuggers.
>It is not intended to be used for thread synchronization.
732:719
08/05/21 19:19:42
>>731
なるほど。その"This function is ..."の1文でいろいろ吹っ切れた気が…。
Suspend/Resumeの機能を実装したければ、外からスレッドに何かシグナルを送って、
スレッド自らの手でSuspendする必要があるわけですね。
SuspendThreadはその部分をよきに計らってくれるものだと勘違いしていました。
どうもありがとう〜。
733:デフォルトの名無しさん
08/05/21 19:32:28
まあ精進してちょ。
734:デフォルトの名無しさん
08/05/21 21:23:54
ふつーはイベントを待つ。
735:デフォルトの名無しさん
08/05/25 07:53:30
グローバルにスレッド管理用のフラグを用意する
スレッド起動時にこのフラグを1にセット
スレッド内で定期的にこのフラグを監視し0になったら途中で終了する
メッセージボックスでキャンセルされた時はこのフラグを0にするだけ
736:デフォルトの名無しさん
08/05/25 08:00:05
マルチスレッドだとスタック領域が別になるから
グローバルで取ったフラグ用変数のポインタをスレッドに最初に渡すのだよ
737:デフォルトの名無しさん
08/05/25 08:02:38
別にクラス内のローカルな変数でもいいんだけどね
その時はクラスのポインタを渡すのだよ
クラス定義を組み込むのを忘れないでね
738:デフォルトの名無しさん
08/05/25 10:51:14
あとvolatileも
739:デフォルトの名無しさん
08/05/25 11:47:42
c/c++のvolatileはいろいろあるから、
ちゃんとmutexなどの同期オブジェクトを使うことをすすめる。
ただwindows限定ならvolatileにメモリバリアの意味があるのだっけ?
740:デフォルトの名無しさん
08/05/25 13:03:14
> c/c++のvolatileはいろいろあるから、
> ちゃんとmutexなどの同期オブジェクトを使うことをすすめる。
もしかして volatile 変数で同期とろうとか思ってる?
741:デフォルトの名無しさん
08/05/25 13:08:25
荒れる予感
742:デフォルトの名無しさん
08/05/25 13:10:20
>>739
メモリバリアの意味はない。
ただ、IA32はコヒーレントキャッシュだから、volatileだけでも
大して問題がないだけ。
743:デフォルトの名無しさん
08/05/25 13:18:53
ていうかこのケースは知らないが
もし「ループを一周余分に回すことになっても問題ない」という
厳密な同期が必要ないものならば、volatileで済むケースはある。
そんなに多くは無いが。
744:デフォルトの名無しさん
08/05/25 13:34:51
>もし「ループを一周余分に回すことになっても問題ない」という
>厳密な同期が必要ないものならば、volatileで済むケースはある。
むしろ今回のケースでは一周分余分に回すのがアウトという状況が考えにくい。
745:デフォルトの名無しさん
08/05/25 14:46:29
一周分余分に回ってアウトなら最初から排他なりセマフォなり入れるしな
746:719
08/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:デフォルトの名無しさん
08/05/25 16:37:42
run()内で例外投げられたらまずくね
748:デフォルトの名無しさん
08/05/26 03:02:25
>>742
ダウト
749:デフォルトの名無しさん
08/05/26 03:25:49
kwsk
750:デフォルトの名無しさん
08/05/26 03:27:13
OoOの問題じゃないかなと思ったり。
751:デフォルトの名無しさん
08/05/26 13:30:52
UOがどうしたって?
752:匿名
08/05/30 15:12:16
スレッドは非常に難しいです。
スレッドを利用しないでコンカレントプログラムが容易にできます。
以下のページが参考になります。
URLリンク(www.cspjapan.org)
753:デフォルトの名無しさん
08/05/30 15:57:17
ばか?
754:デフォルトの名無しさん
08/06/05 15:10:05
生成したスレッドがmallocをしている最中に
SuspendThreadするとどんな問題が発生しますか?
755:デフォルトの名無しさん
08/06/05 15:26:07
mallocの中で排他制御しているだろうから、他のスレッドがmallocを呼
ぶと返ってこなくなるかも。
756:デフォルトの名無しさん
08/06/05 15:27:38
mallocがマルチスレッド対応版だと仮定すると、
ヒープ管理データへのアクセスの排他のために
mutexを握るタイミングがあるはず
そのタイミングでSuspendされると
ほかのスレッドがmalloc/free関連の処理をしようとして
mutex握れなくてずっと待ちに入る
newがmallocをベースにしているならnew/deleteも
はたから見るとハングアップに見える
757:デフォルトの名無しさん
08/06/05 22:23:21
>739
C#のvolatileはメモリバリアの意味もあるよ。
C/C++じゃないよ。
758:デフォルトの名無しさん
08/06/05 22:32:43
ふ〜ん
759:デフォルトの名無しさん
08/06/07 21:41:57
MSDNのSystem.Threading.Thread.MemoryBarrierの説明が微妙でわかりづらい
>MemoryBarrier は、複数の Intel Itanium プロセッサを使用しているシステムなど、
>ウィーク メモリ オーダリングを採用したマルチプロセッサ システムでだけ使用します。
760:デフォルトの名無しさん
08/06/07 23:24:59
memory orderingの知識がないだけじゃね?
strong memory orderingのx86では不要。
シングルプロセッサ(1コア)のシステムでも不要。
weak memory orderingのItaniumを複数使ったシステムでは必要。
書いてあるとおりw
memory orderingはこれでも読んどけ
URLリンク(www.arch.ce.hiroshima-cu.ac.jp)
x86はSPARCのTSOと、ItniumはSPARCのRMOと同じはず
761:デフォルトの名無しさん
08/06/08 00:21:36
質問しようと思ったら>>746に俺が・・・
この場合だとentrypoint内でCloseHandleしてreturn完了後にendthreadex呼ばれるという
挙動であってるのかな?で、ハンドルも問題なく閉じられるのか?
762:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/06/08 13:05:59
MSが言っている"アラート可能な待機状態"とはどういう状態のことですか?
765:デフォルトの名無しさん
08/06/08 13:08:55
何らかのイベント?とかで待機を中断できるってことじゃね?
766:デフォルトの名無しさん
08/06/08 13:11:25
746みたいな事をやるときのboost::threadの楽さと言ったら…。
767:デフォルトの名無しさん
08/06/08 13:12:39
それは、普通の待機状態とアラート可能な待機状態の違いは
スレッドプロセスが__cdeclか__stdcallかの違いである
ということですか?
768:デフォルトの名無しさん
08/06/08 13:24:31
違いますね。APCとか理解できません。
769:デフォルトの名無しさん
08/06/08 13:55:21
>>764
重複I/Oを使うときにのイベント待機に使う。
770:デフォルトの名無しさん
08/06/08 19:17:36
>764
SleepExとかWaitFor〜Exで、bAlertable=TRUEの状態で寝てるとき
771:762です
08/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:デフォルトの名無しさん
08/06/09 02:04:45
JavaのThreadにケチつけるアホがいるスレはここですか?
773:デフォルトの名無しさん
08/06/09 02:17:36
JavaのThread implements Runnableは失敗だろjk
774:デフォルトの名無しさん
08/06/09 18:16:32
Treadクラスの継承が失敗だろ
775:デフォルトの名無しさん
08/06/09 23:04:19
761です。もう全然うまくいかないので、なんか言ってもらうために
スレッド周辺のプログラムをアップしてみます・・・。include "common.h"は消していいです
お願いします><
URLリンク(ccfa.info)
776:デフォルトの名無しさん
08/06/09 23:06:31
よし、何か言ってやる。
>>775 がんばれ!
777:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/06/10 07:15:40
今携帯なんで、後で詳しく見ますが、うまくいかないというのは
これで画像読み込みをしたときに画像読み込みが出来なかったりするんです
実験中には終了時に不正アクセスみたいのが出たり…
779:デフォルトの名無しさん
08/06/10 14:38:51
777が優しすぎる
俺が男なら惚れてたね
780:デフォルトの名無しさん
08/06/10 14:56:56
俺は男だから惚れた
781:デフォルトの名無しさん
08/06/10 16:38:37
じゃあ掘れるのか
782:デフォルトの名無しさん
08/06/10 19:43:21
惚れたけど掘れない。
783:719
08/06/10 20:22:05
いやぁ、勉強になるなぁ…。
784:デフォルトの名無しさん
08/06/11 07:10:26
質問があります
pthreadでは途中でスレッドをキャンセルする場合
pthread_cancelを遅延キャンセルでコールして、
クリーンナップハンドラでリソースを開放するという方法が考えられますが、
C++では実行環境(gcc,glibc)によって、クリーンナップ内でオブジェクトの
デストラクタが呼ばれなかったり、例外処理が行われないなどといったことがあるみたいですが、
「C++ではこのようにしてpthreadを中段させるべき」といった
定石的手法が確立しているのでしょうか?
できればURIなど情報源などもあれば教えてください。
【OS】
Linux2.6
【言語】
C++
【実行環境】
RHEL5(pthread)
【その他突起する事項】
「RHEL5の中のライブラリならサポートしてるので気にするな」ってのは無しで
785:デフォルトの名無しさん
08/06/11 07:47:54
外から中断なんかしない。
当たり前すぎて泣けてくる。
786:デフォルトの名無しさん
08/06/11 12:24:11
>>784
安全に中断させる方法なんて存在しない。
だが、スレッドのエントリ関数のreturnを実行して正しく終了させる方法はいくらでもある。
787:デフォルトの名無しさん
08/06/11 13:55:11
> 「C++ではこのようにしてpthreadを中段させるべき」といった
> 定石的手法が確立しているのでしょうか?
中断通知機構は自分で独自に実装。必ずエントリポイントの関数まで
戻るようにする。
異常時に終了するため、終了用の例外クラスを作成。エントリポイントのみ
でcatchし、他はクラスに対し例外中立なコードを書く。
ソースは俺。
788:デフォルトの名無しさん
08/06/11 14:04:26
>>778
joinせずに終了したか、Thread,Runnableのメモリが誤って解放されたのでは
789:デフォルトの名無しさん
08/06/11 20:40:04
スレッド止めてプロセスにする
790:777
08/06/11 21:51:22
>>775
GetLastErrorの戻り値判定ロジックが逆。
細かい間違いは修正したが普通に動いた。元のろだ?のup方法がわからなかったので↓にup
URLリンク(www11.axfc.net)
DLパスは mt
さすがにmy_ptrとかいうのはboost::shared_ptrに置き換えさせてもらった。
791:デフォルトの名無しさん
08/06/11 22:28:58
アクターモデルって奴の
C++とかjavaとかでのサンプルない?
792:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/06/11 23:27:08
pthread mutexで
読みスレッドが2人
書きスレッドが2人
といる場合、rwlock使うと読んでる間に
書き込もうとしてもロックされる?
794:デフォルトの名無しさん
08/06/12 00:24:12
pthreadは知らないけど一般のReader-Writer-Lockなら排他制御されなぎまずいんじゃね。
Readerのみの場合に排他されないんだと思う。
Reader vs. Reader → 排他されない
Reader vs. Writer → 排他される
Writer vs. Writer → 排他される
795:デフォルトの名無しさん
08/06/12 00:38:59
Pthreadもそうだったと思う
Man読みゃいいんだけどね
796:デフォルトの名無しさん
08/06/12 01:47:42
スレッドAがrdlockする
スレッドBがwrlockしようとする(が、rdlock中なのでブロック)
この状態の時に、スレッドCがrdlockしようとすると
1.スレッドCがrdlockを取得(Aと共存)出来る
2.スレッドB(ロック獲得優先権がある)の処理終了までブロックする
一般的にはどうなる?
・一般的に、rwlockと呼ばれるものの動作として決まっている(どっち?)
・pthreadの標準として決まっている(どっち?)
・何も決まってない(実装依存)
797:デフォルトの名無しさん
08/06/12 01:54:39
>>796
URLリンク(opengroup.org)
> 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:デフォルトの名無しさん
08/06/12 02:00:50
おー、thx
最新レス表示スレッドの検索類似スレ一覧話題のニュースおまかせリスト▼オプションを表示暇つぶし2ch
5389日前に更新/193 KB
担当:undef