05/11/12 23:49:25
ファイル名を返すかわりに直接ハンドルでも返せば?
40:33
05/11/13 00:04:52
>>36
読んでいます難しいです;
>>38
CLコマンドでコンパイルしているのですが/MTオプションを指定してみました。
ファイル送信のバグは今のところ目に付かなくなりました。
しかし"wb"のほうが激しくなりました。
ちなみにCとAPIのみで作成しています。
マルチスレッド用のライブラリについて調べてみようかと・・・
>>39
"rb"のかわりにGetFileAttributes()で判定するようにしてもだめでした。"wb"が開けないのはどうにも・・・
41:デフォルトの名無しさん
05/11/13 00:18:47
まさか、InitializeCriticalSectionしてないとか?
あるいは、違うファイル名を生成する処理がおかしいとか。
あるいは、戻ってきたファイル名の扱いがヒドいとか。
42:デフォルトの名無しさん
05/11/13 00:25:13
>>40
> ちなみにCとAPIのみで作成しています。
へぇー fopen() と言う API がある OS もあるんだ…。
あと、>>39 は、GetFileAttributes() なんかにつ
いて言ってるんじゃないと思う。
そもそも、ファイル名返してもそのファイルを書き込み
オープンする前に他のスレッドが書き込みオープンする
かもしれない。つまり、funk() から戻った時に既に
そのファイル名のファイルが作られてるかもしれないか
ら、ファイル名なんか返しても意味がない。
43:デフォルトの名無しさん
05/11/13 00:33:11
そうそう、普通に「そのまま使える物」を返すか
単に「呼ぶ度に違う名前を生成する関数」を作って、ファイルが開けなければ再試行するとか。
後者のものは、C標準にあるけどな。
44:33
05/11/13 00:45:38
>>41
それは・・・ないとおもいますっ;><
>>42
vc++をインストールしているがコマンドラインでコンパイルしてて
MFCは使わずc言語標準関数とWin32APIで作ってます。
fopen()やfclose()を繰り返すのがまずいのかなと思い"rb"のfopen()を使わないようにしたのを作ってみましたが結果は同じでした。
"wb"がfopen()できないのにファイルポインタは返せないのでは?
初めのを閉じずに使用すれば次のもバグらなくなってウマーということでしょうか。
45:33
05/11/13 01:02:38
とりあえず閉じずに返すようにしてみます。
46:デフォルトの名無しさん
05/11/13 01:29:19
>>44
すまん、>>42 で大嘘書いてた。
fopen(~, "wb") でファイルが作られるから、他のス
レッドがそのファイルを作ることはないはず。まあ、でも
わざわざファイル名を返して戻った先で再度オープンする
ならそのままファイルハンドルを返せばいいと思う。
そもそも、俺なら fopen(~, "a") でファイルを開い
て、fgetpos() で取得したファイルポインタが 0 なら、
そのままそれを返すし、0 でなかったら違うファイル名で
再トライを繰り返すように作ると思う。
47:デフォルトの名無しさん
05/11/13 01:41:44
(他と衝突しない)ファイル名を作る
ファイルを書き込み+排他で作ってファイルポインタを返す
の一連の処理をクリティカルセクションでやるのはどうか.
>>42の「そもそも~」は合ってると思う.
>>33の関数だとファイルを "wb" で作っても fclose ですぐ閉じる
ようになってるから.すでにあるファイルを "wb" で開くと
元のファイルは破壊される.
48:33
05/11/13 03:30:42
TEMPファイルの作成は通し番号で作成するようにしたところバグがでなくなりました。
何とかいけそうです。
現在スレッドを作成するのにCreateThread()関数を使用しています。
調べているとCランタイム関数を使う場合CreateThread()はまずいようです。
以前から、rand()やsrand()を使っているプログラムでもCreateThread()を使っており謎のバグが発生しておりました。
とりあえず_beginthread()を使うように書き直してみます。
今は/MTオプションをつけなくてもコンパイルは通っています。
これが致命的だったのかもorz
49:デフォルトの名無しさん
05/11/13 08:20:26
なぜFILE*を返さないのかわからん。
OSが提供するロックのようなものなのに。
> これが致命的だったのかもorz
_beginthreadexにするのは正しいが
33でやろうとしている内容であれば問題は起きない
50:>>46
05/11/13 10:12:04
>>47
> >>33の関数だとファイルを "wb" で作っても
> fclose ですぐ閉じるようになってるから.すでに
> あるファイルを "wb" で開くと元のファイルは破
> 壊される.
いや、排他が入ってる版ならその前の
fopen(~, "rb") のファイル存在チェックではね
られるから「すでにあるファイルを "wb" で開く」
ことはないはず。
>>48
> TEMPファイルの作成は通し番号で作成するように
> したところバグがでなくなりました。
おいおい、前はどうやってたんだよ…。
> 今は/MTオプションをつけなくてもコンパイルは通っ
> ています。
コンパイルが通れば OK なんて考えてるうちは、マルチ
スレッドプログラムなんか組まない方がいいと思う。
51:33
05/11/14 08:02:54
TEMPファイルの作成は、
以前はtmp.txtが既に存在する場合はtmp(1).txtが存在する場合はtmp(2).txtみたいにしてました。
通し番号の方はtmp1.txt次はtmp2.txt次はtmp3.txtを問答無用に作成するようにしました。
_beginthread()を使用するようにしたところ、以前は謎のアクセスバイオレーションが発生していたのですが
それ以前にどうみてもヌ○ポを踏んでいるようなエラーが出ます。
なんとなくSleep()でタイミングをずらしてみたところエラーが出なくなったりします。
マルチスレッドの場合、同じメモリ領域を同時に”読む”のもNGですか?
if(NULL != *hoge)と*p = hoge;やi = hoge->num;が別スレッドで同時に起きるような場合もNGですか?
52:33
05/11/14 08:08:11
踏んでいる場所を見つけようとチェックを埋め込んでみてもつかまりません。
自分で書いたコードよりも奥の方で発生しているようです・・・。
53:デフォルトの名無しさん
05/11/14 08:11:48
もはやマルチスレッド関係ないだろ。
初心者スレに行け。
create_unique_file()の稚拙なロジックが痛々しい。
54:33
05/11/14 08:14:51
×if(NULL != *hoge)
○if(NULL != hoge) // hogeは構造体へのポインタです。
痛々しいロジックの方は忘れてください;><
55:デフォルトの名無しさん
05/11/14 11:16:38
>以前はtmp.txtが既に存在する場合はtmp(1).txtが存在する場合はtmp(2).txtみたいにしてました。
こんな文章しか書けないくらいだから、コードもとっ散らかってるんだろ。
小学校辺りから「頭の使い方」を勉強しなおしてみたら?
56:デフォルトの名無しさん
05/11/14 17:20:12
重複しないテンポラリファイルなんて、API使えば一発だろ。
57:デフォルトの名無しさん
05/11/14 23:23:11
>マルチスレッドの場合、同じメモリ領域を同時に”読む”のもNGですか?
スレッド生成前にメモリ領域を確保して値しかいじらないのなら、同時に読んでもOK
マルチプロセッサではメモリバリアを使って同期すればOK
メモリ領域を複数スレッド内で確保と消去をくり返すような場合はリードライトロック。
> if(NULL != *hoge)と*p = hoge;やi = hoge->num;が別スレッドで同時に起きるような場合もNGですか?
別スレッドが *hoge ポインタの示す場所をいじるのなら、同期しないと全部アウト。
58:デフォルトの名無しさん
05/11/15 01:05:11
>マルチスレッドの場合、同じメモリ領域を同時に”読む”のもNGですか?
intサイズだったらOKだよ。
前スレでそういう結論になった。
59:33
05/11/15 05:26:59
/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
| 作成された子スレッド内部で継続中flagを立てる前に
| 親スレッドでflagチェック→終了判定→構造体NULLクリア
| していたのがNULLを踏む原因でした。
\
 ̄ ̄ ̄|/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ・∀・) ∧ ∧ < おめーのバグだな、
( ⊃ ) ( ゚Д゚) \____________
 ̄ ̄ ̄ ̄ ̄ (つ_つ__
 ̄ ̄ ̄日∇ ̄\| NullPo |\ ナントカナリソウデス
 ̄ ======= \ イロイロトドウモアリガトウゴザイマシタ
60:デフォルトの名無しさん
05/11/15 08:03:23
親でflag立ててから呼べばいいじゃん。
61:デフォルトの名無しさん
05/11/20 03:06:17
スレリンク(tech板:312-317番)
に書いたんだが、誘導されました。
返答求む。
62:デフォルトの名無しさん
05/11/20 16:27:20
windows には win32 API で色々なイベントを使えるようになってますが、
UNIXではpthreadのイベントを使う以外にないのでしょうか?
63:デフォルトの名無しさん
05/11/20 16:46:47
はぁ?
64:デフォルトの名無しさん
05/11/20 17:19:57
>>62
意味がわかんない。
自分が言ってる単語について全部調べてみたら?
わかんない言葉は使うもんじゃないよ。
65:デフォルトの名無しさん
05/11/20 17:29:22
セマフォをつかって、ある処理に関してロック、アンロックの処理が
したい場合、ソースは以下のようなかんじ問題ないですか?
※以下のプログラムを2つ同時に動かした場合、
セマフォの開放は1つ目のプロセスによって行われているので、
2つ目のプロセスはIPC_RMIDの際に、エラーが出てしまいますよね。
これって、基本的にはどうするといいんですかね?
66:65
05/11/20 17:29:42
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h>
#include <sys/sem.h>
union semun { int val;
struct semid_ds *buf; unsigned short int *array;
struct seminfo *__buf; };
int lock(int argc, char *argv[]) {
union semun semaphore_union;
struct sembuf semaphore_buffer;
int semaphore_id;
semaphore_id = semget((key_t)1000, 1, 0666 | IPC_CREAT);
semaphore_union.val=1; //sem init
if ( semctl(semaphore_id, 0, SETVAL, semaphore_union) != 0 ) {
exit(1); } //lock
semaphore_buffer.sem_num = 0;
semaphore_buffer.sem_op = -1;
semaphore_buffer.sem_flg = SEM_UNDO;
if ( semop(semaphore_id, &semaphore_buffer, 1) == -1 ) {
exit(1); }
sleep(30) // 何かの処理の変わり //unlock
semaphore_buffer.sem_num = 0;
semaphore_buffer.sem_op = -1;
semaphore_buffer.sem_flg = SEM_UNDO;
if ( semop(semaphore_id, &semaphore_buffer, 1) == -1 ) {
exit(1);
}
//sem end
if ( semctl(semaphore_id, 0, IPC_RMID, semaphore_union) != 0 ) {
exit(1);
}
return(0);
}
67:65
05/11/20 17:30:42
//sem end
if ( semctl(semaphore_id, 0, IPC_RMID, semaphore_union) != 0 ) {
exit(1);
}
この際に、一つめのプロセスが既に削除しているので、
2つ目のプロセスでは、エラーが帰ってきてしまいます。
基本的にセマフォの扱いって、どう記述するものなんですか。
68:65
05/11/20 17:31:19
正しいやり方かはわからないが。
①プロセス1の処理が終わったら、セマフォに「プロセス1終わったよ」書き込む。
②「プロセス1終わったよ」になるまで待機してから、
「プロセス2も終わったよ」を書き込んでから、プロセス2を削除。
③「プロセス2も終わったよ」を確認してから、プロセス1を削除
69:65
05/11/20 17:31:49
>>68
それぞれのプロセスをIPC_RMIDさせる直前までwait させろってことですよね。
そのケースは、事前に立ち上がるプロセス数(たとえば、自分で
fork して作成したプロセス)が分かっている場合、有効ですよね。
何個のプロセスがあがるか分からないときの手段としては、
IPC_RMID させる時は、手動で打つがいいのかな。
70:デフォルトの名無しさん
05/11/20 17:35:42
>>65
ここはマルチ「スレッド」のスレだ。
決してマルチ「プロセス」のスレではない。
71:デフォルトの名無しさん
05/11/20 17:38:09
マルチプロセスプロ倉羅民具スレなんてねーんだから
ここでいいじゃん
72:デフォルトの名無しさん
05/11/20 17:39:15
いや、素直にUnixプログラミングスレかUnix板に行くべきだろう。
73:デフォルトの名無しさん
05/11/20 23:03:49
shared libを作ろうとしてまして、
その中でスレッドを起動して使いたいのでつが、
問題ないでしょうか?
74:デフォルトの名無しさん
05/11/20 23:31:14
>69
親が代表してセマフォを造って、削除する。
子供は親の造ったセマフォをみて触るだけ(無ければエラーにする)とか。
セマフォを開いてみて、無ければ造る。
造る時に排他制御して、唯一造れた人が責任をもって廃棄する、とか。
75:65
05/11/21 00:29:05
>>70 >>72
Unixプログラミングすれから、誘導されたんですよ。
>>74
実務レベルだと、
親=オペレータが、起動スクリプト(セマフォ作成)をたたく。
サーバー終了時に、終了スクリプトをたたく。
オペレータ介さないと考えると、init.dに、SXXXXスクリプト)を作成し、
runレベルに合わせて、起動、終了のシンボリックリンクをはる。
なんて感じですかね。
76:デフォルトの名無しさん
05/11/21 02:49:56
>>75
そりゃ気の毒に、誘導が間違ってる。無責任にこの辺に誘導しとくよ。
「VIPPERでもわかるプログラミング」
77:デフォルトの名無しさん
05/11/21 12:01:13
>>73
過去の経験から言わせてもらうとライブラリ側で勝手にスレッドを起動するような
作りはあらゆる意味で良くない。
どうしても必要ならばまずそのスレッドで起こりえる可能性をすべて列挙してみる。
スレッドが起動するという事、その際例外が発生した場合どういう処置がなされるべきか、など。
判断がつかなければコールバック等でそのスレッドのトップレベルループや
ドメインに該当する処理に対してユーザーが干渉できるようにしたほうがいい。
↑domain
|user_thunk_procedure
|thread_callback
これらをドキュメント等も含めきちんと導出できないと第三者にはまず提供できない
代物になる。もしくは欠陥を持ったライブラリが完成する。
78:デフォルトの名無しさん
05/11/22 00:23:28
マルチスレッドの例外処理ってどうやってまつか、みなさん。
79:デフォルトの名無しさん
05/11/22 00:30:02
大域くくって落ちたらやりなおし、
ループでもなんでも、気をとりなおして次の処理。
80:73
05/11/22 01:45:30
>>77
ありがとうございますた、
厳しいみたいでつね、もっと勉強しまつ。
81:デフォルトの名無しさん
05/11/28 01:09:25
winapiスレと迷いましたが、_beginthreadex()に関して質問があります。
現在_beginthreadex(NULL, 0, .....);
としてメモリ割り当てを特に指定していません。
現在は実験のためにあるスレッドをいくつも作りたいのですが、
そうすると、エラーが起こりその原因の場所を調べると
#endif /* _WIN64 */
return HeapAlloc(_crtheap, 0, size);
という箇所でした。毎回ここでエラーが出ているようです。
この原因としてスタック領域のメモリ不足だと自分では思っているのですが、
実際のところはどうなのでしょうか?
また何かいい解決方法を教えていただけないでしょうか?
現在は数十スレですが、将来的には数百スレを扱いたいと考えています。
82:デフォルトの名無しさん
05/11/28 01:33:22
いいえ、その情報だけですとスタックではなくヒープの確保が失敗したと思われます。
マルチスレッド云々以前に初心者歓迎スレ辺りでソースを晒してみては如何でしょう。
83:デフォルトの名無しさん
05/11/28 01:40:39
スレッドが多すぎてヒープ(のアドレス空間)が足りなくなるという可能性も無くはないけど
数十スレッド程度でそんなことになる筈もなく
そもそもスタック領域がヒープを圧迫するかどうかという問題も
84:81
05/11/28 10:47:04
舌足らずですいません。
エラーが起こるのは_beginthreadex()内の処理のようです。
_beginthreadex()を呼び出して目的のスレッドを作成しようとすると
その過程の最中で81のようなエラーが出現してしまいます。
あと、
「メモリがreadになることはありませんでした。」
というメッセージボックスが表示されるのですが
何か関係あるのでしょうか?
スレッド数は32、64、96と増やしていきたいのですが
32の段階でのエラーです。
85:デフォルトの名無しさん
05/11/28 11:28:40
だから、マルチスレッド以前のレベルでバグってるんだろってば。
自分のソースも追えないような蛸なら初心者スレでソース晒せって。
86:デフォルトの名無しさん
05/11/28 13:27:17
> あと、
> 「メモリがreadになることはありませんでした。」
> というメッセージボックスが表示されるのですが
自分で確保したメモリ領域外のアドレスを読みに行ったときに出る.
87:デフォルトの名無しさん
05/11/28 16:58:56
エスパーの俺様が、スレ違いのバグを解決してやろう。
malloc系を呼び出したときにライブラリ内でエラーが起こるのは
ヒープの管理ブロックが壊れている時だ。
つまり、mallocした領域以外をfreeしたり、同じ領域を2度freeしたり
あるいは確保した領域をはみ出して書き込みをした場合に起こる。
88:81
05/11/28 22:43:36
すいませんでした
>87さんのレスを手がかりにmalloc(), free()を中心に調べていったところ
p = (int *)malloc(sizeof(short) * num);
という箇所がありました。
sizeof(int)に直したところ変なエラーはでなくなりました。
心配されていた方々申し訳ございませんでした。
89:デフォルトの名無しさん
05/11/29 00:00:44
だから>82や>85がマルチスレッド以前のバグだって指摘してたのに……
90:デフォルトの名無しさん
05/11/29 04:05:55
うるせえ黙れ
91:デフォルトの名無しさん
05/11/29 08:26:55
>>88
心配してねーよ。
こいつ馬鹿だなと思っていただけ。
92:デフォルトの名無しさん
05/11/29 09:50:47
>>88
誰も心配はしてないとおもいます。アドバイスしてただけ。
日常でもそのような勘違いをしているとなぜあの人は自分のことしか考えないのかと思われるので注意しましょう
93:愛也
05/11/29 15:57:01
質問なんですが・・・・どなたか教えていただけないでしょうか?
(1)
特定のデータを指定するにはアドレス信号を用いる。どれだけのアドレス信号が発行できるかはアドレスバスの本数による。
アドレスバスの本数が8本のときは( 1 )個、12本の時は( 2 )個のアドレスを発行する事ができる。
(2)
容量32KBのメモリがある、このメモリにバイト単位でアドレスをつけた場合(アドレス幅は8ビット)、全アドレスを指定するには、最低( 3 )本のアドレスバスが必要である。
同時に256MBの場合は( 4 )本必要である。
上の問題をどなたかお時間がある方がいらっしゃれば教えていただけないでしょうかぁ??
何卒よろしくお願い致します。
94:デフォルトの名無しさん
05/11/29 16:05:54
>>93
板違い
95:デフォルトの名無しさん
05/11/29 16:43:14
>>93
そのうえ問題自体に間違いがある(w
コピペミスかもしれんが(w
96:デフォルトの名無しさん
05/11/29 20:19:25
HTマシンでpause命令使って効果実感した人いる?
97:デフォルトの名無しさん
05/11/29 23:05:15
メール欄が空ですよ
98:デフォルトの名無しさん
05/12/06 03:43:50
93は、
スレ題名に「マルチスレッドプログラミング相談室」と書いてあるから、
「ここはマ板共用の相談スレに違いない!」と思ったんじゃないの?
99:デフォルトの名無しさん
05/12/06 12:03:49
マ板?
100:デフォルトの名無しさん
05/12/07 16:08:17
Windows でマルチスレッドを実現するには CreateThread API 以外に方法はありますでしょうか?
101:デフォルトの名無しさん
05/12/07 16:55:31
_beginthread
102:デフォルトの名無しさん
05/12/07 21:07:21
>>101
_beginthreadex使えよ。
103:デフォルトの名無しさん
05/12/09 18:32:43
つうか何がしたいんだ
104:デフォルトの名無しさん
05/12/09 18:52:57
いろんな恋がしたい
105:デフォルトの名無しさん
05/12/10 01:12:51
マルチフ恋奴
106:デフォルトの名無しさん
05/12/13 10:40:34
ほしょ
107:デフォルトの名無しさん
05/12/13 22:06:28
>>104
マルチスレッドな恋なんかしてると火吹くぞ
108:デフォルトの名無しさん
05/12/13 23:24:21
俺のセマフォは3カウントまで。
109:デフォルトの名無しさん
05/12/14 00:13:25
セマフォなんてニッチで泥臭いものは今日日使わないよ
110:デフォルトの名無しさん
05/12/14 00:29:54
オレのMutexは一度もLockされたことがない…orz
111:デフォルトの名無しさん
05/12/14 00:32:21
そこはまさにCriticalSectionなので、触れてはいけない。
112:デフォルトの名無しさん
05/12/14 00:33:55
一生一WorkerThread。
113:デフォルトの名無しさん
05/12/14 00:35:11
オレのFutureはいつまでたっても実体を返さない…orz
114:デフォルトの名無しさん
05/12/14 00:36:37
オレのQueueはいつも空っぽ…orz
115:デフォルトの名無しさん
05/12/14 00:44:57
Terminateされたい性分なんです、スレッド失格でしょうか?
116:デフォルトの名無しさん
05/12/14 00:50:19
だれかJoinしてクレー!
117:デフォルトの名無しさん
05/12/14 01:10:22
オレのQueue、気付いたときにはStackになってた
118:デフォルトの名無しさん
05/12/14 01:41:29
恋はいつも非同期(asyncronous)
119:デフォルトの名無しさん
05/12/14 02:02:00
クリスマスなのにDaemonです…orz
120:デフォルトの名無しさん
05/12/14 02:45:54
僕の人生Suspendしています。誰が解除してくれるんですか?
121:デフォルトの名無しさん
05/12/14 03:08:52
俺はreturnしちゃったよ
122:デフォルトの名無しさん
05/12/14 07:50:37
signal投げてくれる筈のプロセスがゾンビになっていた件について
123:デフォルトの名無しさん
05/12/14 07:55:39
それマルチスレッドじゃねーし
124:デフォルトの名無しさん
05/12/14 21:50:08
彼女といつも同期に失敗しまつ
125:デフォルトの名無しさん
05/12/14 21:52:06
俺はいつもシングルスレッド。
126:デフォルトの名無しさん
05/12/15 00:29:14
漏れのセフレはヂュアルコアだから2穴使って楽しめるよ。
127:デフォルトの名無しさん
05/12/17 01:08:57
おまいら、そろそろ戻ってこい
128:デフォルトの名無しさん
05/12/17 04:50:34
goto 107
129:デフォルトの名無しさん
05/12/17 08:34:28
mutex と spin lock の使い分けの基準て何?
130:デフォルトの名無しさん
05/12/17 10:49:07
使い分けってお前
131:デフォルトの名無しさん
05/12/17 15:45:08
mutex: 居間のテレビのチャンネル権取得に使う
spin lock: 朝、トイレの空きを待つ時に使う
132:デフォルトの名無しさん
05/12/17 15:57:25
後者、spin lockになるのはガマン出来ないときに限られると思われ
133:デフォルトの名無しさん
05/12/17 16:18:01
スピンロックって、カーネルモードへの移行よりも短い時間しかブロックされない処理、
例えば単純な変数の読み書きなんかに積極的に使いたくなるのだけれど
シングルプロセッサのシステムで、
ロックしているときにコンテキストスイッチが起きて
別スレッドがロック取得しようとすると
すげー時間が無駄になるんだよね。
それがちょっと嫌。
134:デフォルトの名無しさん
05/12/17 20:56:42
>>133
知ったかはよくないぞ。入社2年目のおぬし。天狗の鼻をへし折られろ。
135:デフォルトの名無しさん
05/12/17 21:16:38
我が社では、spin lock の事を
フレンドリーに「ぐるぐるくん」と呼んでいる。
136:デフォルトの名無しさん
05/12/17 21:35:35
我が社では回転元彌チョップと呼んでいる。
137:129
05/12/17 22:48:09
>>131
よくわからんです
>>133
その単純な変数の読み書き以外に、どうしても spin lock を使い
たいんじゃ! とか、spin lock じゃないとうまくいかないような、
典型的なケースってないすか?
138:デフォルトの名無しさん
05/12/18 00:05:24
>>134
じゃあ、どこがおかしいのか指摘しろよ。
業界最底辺を何年も続けてる事だけが自慢の
低脳プログラマさんよ。
マルチプロセッサでも、
ロックを取得している状態で実行権を奪われたら起こりうるのは確かだけどな。
139:デフォルトの名無しさん
05/12/18 00:40:53
>>138
だれか解読頼む。
140:デフォルトの名無しさん
05/12/18 01:43:49
>>138
お前の存在そのものがおかしいことを指摘してやらんでもない。
141:デフォルトの名無しさん
05/12/18 01:46:16
指摘してほしいのに しろよ はないだろ。
せめて、「わたくしは無知なので、できれば、ご指摘いただけないでしょうか?」だろ。
誠心誠意で言葉に気をつけろ。
142:デフォルトの名無しさん
05/12/18 01:51:21
ナニこいつ
143:デフォルトの名無しさん
05/12/18 01:59:03
具体的に指摘しないのは荒らしと同じだから放置汁
144:デフォルトの名無しさん
05/12/18 14:48:34
チョンはすぐにファビョるからやあねえ。
145:デフォルトの名無しさん
05/12/18 18:57:20
Win32(XP)で下のような排他制御を考えないプログラムを書いて
実際にハングするところを確かめたかったのですが、何度実行しても上手くハングしてくれません
たまたま運が良くてハングしなかっただけなのでしょうか?ご教示願います
#include <stdio.h>
#include <windows.h>
#include <process.h>
unsigned __stdcall mythread(LPVOID);
int main(){
unsigned int thID;
HANDLE hTh = (HANDLE)_beginthreadex(NULL, 0, mythread, NULL, 0, &thID);
for (int i = 1; i <= 100; i++) {
FILE *fp = fopen("test.txt", "a");
fprintf(fp, "Main---%d\n", i);
fclose(fp);
}
WaitForSingleObject(hTh, INFINITE);
CloseHandle(hTh);
return 0;
}
unsigned __stdcall mythread(LPVOID lpx)
{
for (int i = 1; i <= 100; i++) {
FILE *fp = fopen("test.txt", "a");
fprintf(fp, "Thread---%d\n", i);
fclose(fp);
}
return 0;
}
146:デフォルトの名無しさん
05/12/18 19:34:13
この程度でハングはしないと思うが、
同期とらない=ファイルの中身はグチャグチャになるの?
って意味ならば出力されたファイルを読め。
147:デフォルトの名無しさん
05/12/18 19:38:13
>>146
ファイルもぐちゃぐちゃになりません。きちんと出力されます
また、一度に書き込む文字列のサイズを100KB程度と大きくしてもきちんとと出力されます
しかし、どちらかのスレッドにSleep(0)等を入れる程度でぐちゃぐちゃになります
境界はどこに有るのでしょうか?
148:デフォルトの名無しさん
05/12/18 21:36:48
ヒント:ストリーム系はバッファリングされるから混ざりにくい。
149:デフォルトの名無しさん
05/12/19 00:03:34
fprintf-fcloseの間にスレッドが切り替わらなければセーフ。
んで、100回くらいのループではWindowsのタイムスライスに
引っかからなかったりするのでは。
マルチプロセッサなら、カナリヒドい事になりそうな気がするのだけれど。
150:デフォルトの名無しさん
05/12/19 06:15:26
>>149
> fprintf-fcloseの間にスレッドが切り替わらなければセーフ。
そうとは限らない。
151:デフォルトの名無しさん
05/12/19 10:16:27
>>148
「一度に書き込む」っていってんだから、
バファリングの有無は関係ないような気がするんだけど。
152:デフォルトの名無しさん
05/12/19 21:48:15
そもそもハングするのか? ハングはしないだろ
153:145
05/12/20 01:28:57
いろいろ調べてましたが
IO絡みの関数は基本的にスレッドセーフに作られてるから
ってのが答えみたいです
お騒がせしました
>>149
それは違います。たとえfcloseをコメントアウトしてもハングしません
>>152
ハングはしないようですね
このページに「大抵ハングしてしまいます」と書かれていて気になったのです
URLリンク(www.kumei.ne.jp)
まあこのページに限らずネット上でマルチスレッドを初心者向けに教えているサイトでは
大抵同じような書かれ方がされてるので、
もしかすると私の検証が不十分なのかもしれませんが・・・
154:デフォルトの名無しさん
05/12/20 04:36:05
同時に書き込んで壊れなくても
後からの書き込みで前の書き込みは上書きされて消える訳だが
155:デフォルトの名無しさん
05/12/24 14:28:30
>>153
ランタイムライブラリがスレッドセーフで無い場合はハングするかもしれないけど、
VS2005からシングルスレッドのランタイムは無くなっているなあ。
156:デフォルトの名無しさん
05/12/24 14:44:54
「ハングする」なんて言い方は止めて、
「動作が未定義」くらいにしてくれないか。
本当にハングアップするかどうかを問題にしているんじゃないだろ?
157:デフォルトの名無しさん
05/12/25 13:24:46
>>156
このマニアめが。
158:デフォルトの名無しさん
05/12/25 13:38:00
/MT ってやってればたいがい大丈夫だろうけど、スレッドセーフでない関数で
gethostbynameとかが未定の動作されるとかなり困る、
無理矢理排他同期とって使ってるけどなんかかっこ悪い。
159:デフォルトの名無しさん
05/12/25 13:45:27
winsockのgethostbynameはスレッドセーフじゃなかったっけ?
160:デフォルトの名無しさん
05/12/25 13:49:25
/MTってことはWindows?
getaddrinfoはMT-Safeでしょ。
URLリンク(msdn.microsoft.com)
には明記してないけど、gai_strerrorは違うから~って書いているくらいだから。
161:デフォルトの名無しさん
05/12/25 13:54:49
明記してあるな。
>Remarks
>The gethostbyname function returns a pointer to a hostent structure-a structure allocated by
>Windows Sockets. The hostent structure contains the results of a successful search for the
>host specified in the name parameter.
>The application must never attempt to modify this structure or to free any of its components.
>Furthermore, only one copy of this structure is allocated per thread, so the application should
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> copy any information it needs before issuing any other Windows Sockets function calls.
162:デフォルトの名無しさん
05/12/25 13:57:38
struct hostent *host;
host = gethostbyname(argv[1]);
ってな形だし、どうみてもスレッドセーフでないと思ってた。
スレッド固有メモリなんてものでも使ってるのかな。
163:デフォルトの名無しさん
05/12/25 14:14:38
>>161
それだけでMT-Safeだとは限らない。
164:デフォルトの名無しさん
05/12/25 14:50:26
getaddrinfo ってのがあるんだ、
参考にしてた本が古っかったので知らなんだ。
該当箇所を書きかえねば orz
165:デフォルトの名無しさん
05/12/25 15:28:14
2ちゃんで書き込みするときの文字2048制限解除方法誰か教えてください。
166:デフォルトの名無しさん
05/12/25 15:29:18
制限解除して書き込んでる人が増えてるんですが
167:デフォルトの名無しさん
05/12/25 15:38:13
>>164
古いWindowsではありませんのでその辺は配慮を。
168:デフォルトの名無しさん
05/12/26 03:11:55
「スレッドできる」と「スレッドでファイル操作しても問題ない」は同義じゃないよなあ。
単一リソース操作は対策しないと普通は競合するよ。
169:デフォルトの名無しさん
05/12/26 19:09:27
マルチスレッドなサーバプログラムを作ってみようかと思ってます
クライアント数が少ない場合1クライアントに1スレッドを割り当てればいいかなと思いますが
クライアント数が多い場合はどういった方法が良いんでしょうか?
1スレッドあたりのクライアント数を決めてスレッドごとにselect()するとか
親スレッドでselect()して処理を別スレッドに任せるとか一応考えてはみていますが
どういった方法がスタンダードなんですかね?
170:デフォルトの名無しさん
05/12/26 20:42:42
ジョブキュー
171:デフォルトの名無しさん
05/12/26 22:37:27
+スレッドプール
172:デフォルトの名無しさん
05/12/26 23:38:08
裏技としてApache
勉強にはならんな・・・
173:デフォルトの名無しさん
05/12/27 13:56:11
apacheって何言ってんの?
ネットワークプログラミング相談室にも沸いたバカだろか。
174:デフォルトの名無しさん
05/12/28 15:39:12
なぜそこで、あと半歩踏み込んで「apache馬鹿よね~」とか言えないよねぇ
175:デフォルトの名無しさん
05/12/28 16:51:48
おバカSunよね~
176:デフォルトの名無しさん
06/01/02 08:35:56
くだらない質問ですみませんが
TCPで同じディスクリプタにread()するスレッドとwrite()するスレッドを分けたとき
全二重だから同時にread()とwrite()を実行しても問題ありませんよね?
あと片方が同期無しでclose()するのって問題ありますかね
177:デフォルトの名無しさん
06/01/02 08:40:05
同時にread/writeしても問題なし。
HTTPサーバのようなものを作ってるなら相手が一方的にclosesocketしたくらいでおかしくなっては困る。
178:デフォルトの名無しさん
06/01/02 12:25:53
Solaris2.xではデッドロックしてたなあ(遠い目)
179:デフォルトの名無しさん
06/01/03 03:50:46
x86 とかで int の値を書き込むスレッド(A)と読み込むスレッド(B)がある場合,
更新途中の値が(つまり 32bit 中の 16 bit が新しい値で残りが古いままとか)
B に見えてしまうということはありうるでしょうか?
# long とかだとまずいですよね.
180:デフォルトの名無しさん
06/01/03 04:40:29
>>179
前スレで延々やってたと思う
そこが本題でなければ、排他で済ませて先行った方がいいと思うヨ
181:デフォルトの名無しさん
06/01/03 04:56:02
>>180
レスありがとうございます.前スレの読み方がよく分からないので憶測になっ
てしまいますが,前スレの議論では結局「あり得る」という結論に至ったとの
理解で良いでしょうか?
参考になりそうな資料へのポインタを教えて頂けるとうれしいです.
> そこが本題でなければ、排他で済ませて先行った方がいいと思うヨ
性能的な面から可能な限り B に対する排他処理は避けたいと考えています.
182:デフォルトの名無しさん
06/01/04 15:07:19
>>181
OSに用意されている、Atomicな書き換えAPIを利用すれば宜しかろう。
32ビットバスでアライメントも合っていれば素直にAtomicに書き換わると思うが。
183:デフォルトの名無しさん
06/01/04 16:15:06
レスありがとうございます。調べてみます.
184:デフォルトの名無しさん
06/01/13 02:07:27
マルチスレッドプログラミングで注意することを列挙してくれ。
185:デフォルトの名無しさん
06/01/13 02:19:22
ひとつ!急いで口で吸え!
186:デフォルトの名無しさん
06/01/18 14:53:41
ふたつ! 不埓な悪行三昧!
187:デフォルトの名無しさん
06/01/18 16:18:23
みっつ! 想定の範囲内です。
188:デフォルトの名無しさん
06/01/18 16:55:53
よっつ、読んでも書いちゃダメ
189:デフォルトの名無しさん
06/01/18 16:56:28
いつつ、いつも心に排他処理
190:デフォルトの名無しさん
06/01/18 16:59:48
むっつ、無理せずmutex
191:デフォルトの名無しさん
06/01/18 17:21:48
ななつ、仲良くSemaphoeで共有
192:>>46
06/01/18 23:32:09
やっつ、やっぱりここでも排他処理
193:デフォルトの名無しさん
06/01/19 00:43:25
ここのつ!心を鬼にして排他処理
194:デフォルトの名無しさん
06/01/19 01:03:03
糞スレ立てんな
195:デフォルトの名無しさん
06/01/19 01:39:58
とう、でとうとう割り込まれた。
排他だけじゃなく、割り込み禁止も忘れないでね☆
196:デフォルトの名無しさん
06/01/21 01:53:34
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)で作ったイベントに対して
SetEvent(hEvent);←TRUEがかえる
でも、その次に
WaitForSingleObject(hEvent, 0)とやってもWAIT_OBJECT_TIMEOUTがかえる。
こういうことがおきているのですがどのようなことが考えられますか?
197:デフォルトの名無しさん
06/01/21 07:15:10
>>196
SetEventは成功したけど、イベントオブジェクトがシグナル状態になる前にWaitForSingleObjectがタイムアウトした。
198:>>46
06/01/21 09:16:54
>>196
他のスレッドが一生懸命 ResetEvent(hEvent) を
やってる。
199:196
06/01/21 14:20:25
>>197
SetEventってシグナル状態にした後で戻るわけではないのですか?
>>198
ソースを見る限りほかのスレッドが触ることはなさそうなのですが確信持てないです。
SetEventとWaitForSingleObjectの間で他のスレッドにスイッチしなければそういうことはおきないですよね?
であれば確認のためにはスレッドのスイッチをSetEventとWaitForの間で抑制してあげればいいですよね。
なにか、任意のコードブロックではスレッドスイッチを禁止する方法はないでしょうか
200:デフォルトの名無しさん
06/01/21 14:26:18
ちょっと確認だが、WaitForSingleObject()の第二パラメータの0ってNoWaitだよな?
単に待てば委員で内科医?
201:デフォルトの名無しさん
06/01/21 14:42:02
>196のままのコードを実行してみたけど、ちゃんと0が帰ってきたよ。
202:デフォルトの名無しさん
06/01/21 15:04:56
>>199
>>196の事象が事実であるなら、そういうものだと思って使うべき。
嫌なら別の手段を用いるべき。
203:196
06/01/21 15:47:24
>>200
SetEventしてそれが本当にシグナルになったかを見るためにWaifFor・・したのですが、
それがなぜかシグナルになっていないのです。
>>201
検証ありがとうございます。>>196のままのコードだとそうなると思いますが、実際にはほかのスレッドもいるので
何が起きているかはよくわかっていません。(デバッガでステップ実行したりデバッグライトを入れるだけで動きが変わるため)
とりあえず、月曜にほかのスレッドがResetしていないか確認したいと思います
あとSetEventって非同期に動いたりしませんよね?
SetEvent(hEvent);
ここで誰かがResetEventしない限り下はTRUEにならないですよね?
if(WaitForSingleObject(hEvent,0)==WAIT_OBJECT_TIMEOUT)
{
}
204:デフォルトの名無しさん
06/01/21 17:01:11
>>203
だから、WaitForSingleObject(hEvent, INFINITE)してみたら?
205:デフォルトの名無しさん
06/01/21 21:15:12
そもそも、WAIT_OBJECT_TIMEOUTってなんだ?
成功:WAIT_OBJECT_0 or WAIT_TIMEOUT or WAIT_ABANDONED
失敗:WAIT_FAILED
のいずれかが、WaitForSingleObject()の戻り値なんだが・・・
とりあえず、該当部分のコードを晒せ、晒したくなかったらコピペも満足にできない房は二度とくんな。
206:>>46
06/01/21 23:02:03
>>199
> ソースを見る限りほかのスレッドが触ることはなさそ
> うなのですが確信持てないです。
はぁ? 悪いけど、変数がどっからアクセスされるか自信
が持てないなんて言う奴にはマルチスレッドプログラムは
無理だよ。あきらめたら?
>>203 で、デバッガとか言ってるが君がやることは、デ
バッガでプログラムを追っかけることではなく hEvent
で全ソースに対して findstr することだと思う。
(そこらじゅうで hEvent 使ってるなら、問題のところ
の変数名を変えるべき。)
>>201
うちでも、CreateEvent() ~ SetEvent() ~
WaitForSingleObject() ~ CloseHandle() を
10,000,000 回実行したが、WAIT_OBJECT_0 しか
返らないよ。
>>202
その考え方はおかしいだろ。
>>196 みたいな動きをするイベントなんて使い物にな
らないと思う。
207:デフォルトの名無しさん
06/01/22 08:57:50
>>206
>>>196 みたいな動きをするイベントなんて使い物にな
>らないと思う。
eventは許可するまで待たせておくことが目的の物だから、setは少しくらい遅れても良いと思う。
acquireI->releaseする同期モノのreleaseも同じ。
208:>>46
06/01/22 10:13:10
>>207
少しってどれぐらい?
1秒なの? 1ms なの? 1μs なの?
他のスレッドに対して set の伝播が遅れるのは問題ない
けど、自スレッドに対して SetEvent() してからイベン
トがセットされるまでの間に「隙間」があるのは問題。
例えば、
SetEvent(hEvent); // hEvent は、ワーカースレッドか処理終了でセットする。
StartWorkerThread(); // 処理開始指示。
while(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT){ // 終了したか?
// 終了してないなら、他のことしてようっと。
}
(こんなプログラムは組むなと言う意見はまた別の機会に。)
と言うプログラムがうまく動かない。
動かないだけなら、まだしも下手するとうまく動いたり動
かなくなったりすると言う最悪パターンになる。
マルチスレッドプログラムやるなら「隙間」をもっと意識
できないとはまるよ。
209:デフォルトの名無しさん
06/01/22 12:18:00
>>208
「こんなプログラムは組むな」
210:デフォルトの名無しさん
06/01/22 12:45:43
>自スレッドに対して SetEvent() してからイベン
>トがセットされるまでの間に「隙間」があるのは問題。
いやだから、その隙間は無いんだって。
というか、先頭のSetEventはResetEventの間違いだよな、な。
211:デフォルトの名無しさん
06/01/22 16:13:56
スレ違いスマソ
下のスレでマルチコアについて侃侃諤諤の論争してるんですけど、
みなさんはこれからのマルチコア時代についてどう捉えていますか?
Intelの次世代CPUについて語ろう 21
スレリンク(jisaku板)
212:デフォルトの名無しさん
06/01/22 17:12:45
>>208
次にタスクスイッチが起こったときにsetしてくれればいい程度に思って使ってるね、私は。
>while(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT){ // 終了したか?
普通スレッド終了の検知はスレッドのハンドルをWaitForSingleObjectの引数にする。
わざわざeventなんて作らない。
スレッドをプールするなんて言い訳は聞かない。
>>211
面倒なことはOSに任せて今まで通りにやる。
213:>>46
06/01/22 20:04:17
>>210
すまん、勘違いだ。
セット側はさすがにちょっと考えにくいな。
(まあ、リセット側も無理矢理だが。)
ただ、セット側とリセット側で挙動が違うのはちょっと気
持ち悪い。
>>211
マルチコアって言ったって、マルチプロセサの一形態だろ。
別に何か変えないといけないのか?
専用のチューニングが必要になったらそのとき勉強するよ。
>>212
> 普通スレッド終了の検知はスレッドのハンドルを
> WaitForSingleObjectの引数にする。
スレッドの終了 ≠ 処理の終了
誰も、スレッドの終了の検知方法なんて聞いてないぞ。
最近知ったので、知ったかしたくなったのか?
214:デフォルトの名無しさん
06/01/22 20:06:09
さーしったかしったかたーこうりんだー
さーしったかしったかたーこうりんだー
みぎあしくんひだりあしくん
215:デフォルトの名無しさん
06/01/22 20:17:49
>>214
気が済んだか?
すっきりしたら、違うスレに行ってくれよな。
216:デフォルトの名無しさん
06/01/22 20:27:26
>>213
>スレッドの終了 ≠ 処理の終了
そういうことを言いたかったのか。
217:デフォルトの名無しさん
06/01/22 21:08:07
VC6.0でスレッドを生成するために、
_beginthreadexを使おうと思っていますが、
1プロセスあたりに生成できるスレッド数って
決まっているのでしょうか?
MSDNのCreateThreadのヘルプには、
2028との数字がありますが・・・
218:デフォルトの名無しさん
06/01/23 00:53:27
スタック用のメモリ領域が1MB確保されるんじゃなかったかな
219:デフォルトの名無しさん
06/01/23 00:57:58
そんなにスレッド作ってどうするの?
220:デフォルトの名無しさん
06/01/23 22:02:30
特殊用途か設計ミスか勘違い
221:デフォルトの名無しさん
06/01/23 22:48:39
>>217-220
まさに、その「設計ミス」(要は、バグ) で、
スレッド作りすぎてアプリケーションエラー
出しまくった俺が来ましたよ。
うちの環境だと、1600個位でおかしくなった。
ただスレッドを生成するのが、メーカー提供の
COM の中なので、生成する時にどんなエラー
が返ってきているかはよくわからん。
222:デフォルトの名無しさん
06/01/24 14:21:13
なんじゃそりゃ(´・ω・`)
223:デフォルトの名無しさん
06/01/24 23:34:23
>>196
例えば
1.CreateEvent の第2引数が FALSE(自動リセットオブジェクト)である
2.スレッドAが WaitForSingleObject(hEvent, INFINITE) している
3.スレッドBが SetEvent(hEvent) を呼び出す
4.スレッドAが待機状態から解放される
5.スレッドBが WaitForSingleObject(hEvent, 0) を呼び出す
こういう場合、他のスレッドが ResetEvent しなくても 5.は WAIT_TIMEOUT
を返すけど、CreateEvent の第2引数が TRUE なら WAIT_TIMEOUT を返すのは
おかしいね。
224:デフォルトの名無しさん
06/01/25 20:29:21
WAIT_OBJECT_TIMEOUT
って書いてたことがばれて逃げてったやつに追い討ちかけんなよ。
225:デフォルトの名無しさん
06/01/27 17:33:55
A.EXE と B.DLL があり、B.DLL が foo() という関数をエクスポートしており、
foo() は内部的に strtok 等の C ランタイム関数を呼ぶとする。
B.DLL 内部で _beginthread(ex) したスレッドの中で foo() を呼ぶのは当然問題
ないはずだけど、A.EXE が内部で CreateThread または _beginthread(ex) した
スレッドの中で B.DLL の foo() 関数を呼び出した場合、メモリリークするの?
B.DLL が DLL_THREAD_ATTACH/DETACH できちんとスレッドごとの初期化・後始末
をしていれば大丈夫そうな気がするんだけど、VC とか BC とかの C ランタイム
ライブラリはこの辺どうなってるんだろう。
226:デフォルトの名無しさん
06/01/27 18:21:34
CreateThreadで作ったスレッドはCランタイムライブラリを使ってはいけない。
スレッド内部でCランタイムライブラリを使いたい場合は、_beginthreadexを使おう。
_beginthreadはVBみたいなもんだと思おう。
詳しくはMSDNライブラリを参照のこと。
URLリンク(msdn.microsoft.com)
ランタイム ライブラリ リファレンス
_beginthread、_beginthreadex
URLリンク(www.microsoft.com)
プラットフォーム SDK
CreateThread
URLリンク(support.microsoft.com)
C ランタイム(CRT)関数と CreateThread ()を使用するの、説明
227:デフォルトの名無しさん
06/01/27 20:30:26
>>225
むしろ逆。
B.DLL内部で_beginthread(ex)したスレッドからA.EXE中の関数bar()を呼ぶとリークする。
ただしA.EXEがCRTとスタティックリンクしていて実行環境がWindows Server 2003より前の場合。
URLリンク(codezine.jp)
CRTはソース公開されてるから気になるなら読むといいよ。
Express Editionだと付いてるか知らんけど。
228:225
06/01/27 23:32:29
>>227
> B.DLL内部で_beginthread(ex)したスレッドからA.EXE中の関数bar()を呼ぶとリークする。
コールバック関数とかも、そのコールバック関数が自EXE で _beginthread(ex)
したスレッドから呼ばれないなら C ランタイムを使えないことになりますね。
>>227 の質問を繰り返すことになりますが、A.EXE 内部で _beginthread(ex) した
スレッドから B.DLL 中の関数 foo() を呼ぶのは大丈夫なんでしょうか。
DllMain の DLL_THREAD_ATTACH/DETACH はこのへんの問題を解決するための
機構だと思ってるので、きっと大丈夫なんだと自分に言い聞かせるようにし
てるんですが…。
229:225
06/01/27 23:34:18
>>227
> CRTはソース公開されてるから気になるなら読むといいよ。
VC6 のソースを見る限りでは、DLL_THREAD_ATTACH/DETACH でスレッドごとの
初期化/後始末をしているようです。
CRT を使う DLL に関して、VC6 のソースを見た感じでは、その DLL が
C ランタイムをスタティックリンクしている場合は _DllMainCRTStartup 内で
DllMain を呼ぶ前に DisableThreadLibraryCalls を呼ばないようです。
MSVCRT.DLL を使用する場合は、ユーザー定義の DllMain がない場合のみ、
DisableThreadLibraryCalls を呼んでいるようです。DllMain があった場合、
DllMain 内部で DLL_THREAD_ATTACH/DETACH が必要になる可能性があるから
DisableThreadLibraryCalls を呼ばないようにしてるのでしょう。おそらく。
だから、EXE 側で作成したスレッド内で、DLL 側の C ランタイム関数を使う
関数を呼び出しても、DLL_THREAD_DETACH で後始末が行われるのでメモリリーク
は発生しないのではないかと思ってますが、それが明記されているドキュメント
が見当たらないので気になっています。
230:225
06/01/27 23:36:13
EXE 側で作成したスレッド内で、DLL 側の関数(内部的に C ランタイム関数を
使うもの)を使えない(使うとメモリリークする)としたら、まともなマルチ
スレッドアプリケーションなんて開発出来ない気もします。
せめて malloc/free/new/delete くらいは問題なく使えるようでないと…。
でも、
URLリンク(support.microsoft.com)
を見ると malloc も駄目みたいですよね…。実際のところどうなんでしょ。
231:デフォルトの名無しさん
06/01/28 07:40:26
実際のところってもなあ
hackして怪我するのってあほらしくないか
232:デフォルトの名無しさん
06/01/28 10:30:25
>>230
Cランタイム関数はスレッドなんてのが出来るまえのシロモノだからね。
漏れの知る限りでは、
リンクしてるCランタイムライブラリが同じでマルチスレッド対応なら、
EXEとDLLで相互に呼び合いとかしても別段問題ない。
なぜなら、Cランタイムが使う領域は_beginthread*()でスレッド生成時に
スレッドローカルに確保されて、そちらが使用されるから。
(→see AdvancedWindows)
ただし、_*thread*()はランタイムライブラリに含まれる関数だから、
異なるライブラリを混在すると問題になる場合がある。
MS libcmtとMSVCRTの混在も危険。
(→see MSDNの/MDあたりのオプションのヘルプ)
233:デフォルトの名無しさん
06/01/28 10:43:44
>>230
それ英語版の方読めよ。機械翻訳で日本語として成立してない。
URLリンク(support.microsoft.com)
> スレッド内部でCランタイムライブラリを使いたい場合は、_beginthreadexを使おう。
で
> calling malloc(), fopen(), _open(), strtok(), ctime(), or localtime()
も問題なし。_endthreadex() が、CRT per-thread data-block を後始末してくれるから。
234:225
06/01/28 14:56:16
ちょっと試してみました。
B.DLL
void foo(void)
{
char dummy[256];
strtok(dummy, "");
}
A.EXE
DWORD WINAPI ThreadProc(void *pvParam)
{
foo();//B.DLL 内の関数
return 0;
}
void test(void)
{
HANDLE hThread;
DWORD dwThreadId;
int i;
for(i = 0; i < 10000; i++){
hThread = (HANDLE)CreateThread(NULL,
0,
ThreadProc,
0,
0,
&dwThreadId);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
}
235:225
06/01/28 14:57:27
>>234 の続き
1.A.EXE: BCB5 で作成、B.DLL: VC6 libcmt.lib で作成
2.A.EXE: BCB5 で作成、B.DLL: VC6 msvcrt.lib で作成
3.A.EXE: BCB5 で作成、B.DLL: BCB5 で作成
結果:
1:DllMain で DisableThreadLibraryCalls を呼ぶとメモリリークする
(test を呼ぶ度にメモリ使用量が増える)
DllMain で DisableThreadLibraryCalls を呼ばなければメモリリークしない
(test を何回呼んでもメモリ使用量は変わらない)
2:DllMain で DisableThreadLibraryCalls を呼んでも呼ばなくてもメモリリークしない
3:DllMain で DisableThreadLibraryCalls を呼んでも呼ばなくてもメモリリークする
ちなみに
void foo(void)
{
char* dummy = (char*)malloc(128);// char *dummy = new char[128];
free(dummy);// delete[] dummy;
}
の場合、どの場合においてもメモリリークしない
236:225
06/01/28 14:59:56
>>235 の続き
結論:
BCB5/VC6 で作成した B.DLL においては、C ランタイムルーチンのうち、少なくとも
malloc/free/new/delete しか使わない分には、A.EXE で作成したスレッド内で B.DLL
の関数を呼び出してもメモリリークしない。スレッドの作成に _beginthread(ex) を
使う必要もない。
VC6 で MSVCRT.DLL とリンクする B.DLL では、A.EXE で作成したスレッド内で B.DLL
の関数(内部で C ランタイム関数を呼ぶもの)を呼び出してもメモリリークしない。
VC6 で libcmt.lib とスタティックリンクする B.DLL では、DllMain で
DisableThreadLibraryCalls() を呼ばなければ、A.EXE で作成したスレッド内で
B.DLL の関数(内部で C ランタイム関数を呼ぶもの)を呼び出してもメモリリーク
しないが、DisableThreadLibraryCalls()を呼ぶと、B.DLL が内部で呼び出している
C ランタイムルーチンによってはメモリリークする可能性がある。
他にも色んな組み合わせが考えられますが、とりあえず自分が知りたかった
「A.EXE で作成したスレッド内で B.DLL 内の関数を呼び出してもメモリリーク
しないのか」は検証出来ました。この程度の実験で検証出来たと断言して良い
のかはわかりませんが。
BCB5 の C ランタイムルーチンは DLL_THREAD_ATTACH/DETACH をきちんと処理して
いないものと思われます。BCB5 で作った DLL はマルチスレッドアプリケーション
からは使いにくいですね。
VC7 以降とか GCC とかではどうなんでしょうね。
検証の仕方が間違ってたらご指摘下さい。
237:デフォルトの名無しさん
06/01/28 15:25:22
>>236
率直に言えば無意味な検証。
というのは、メモリリークだけが問題ではないから。
仮にメモリリークしていなかったとしても、
複数のスレッドで同時に1つのワークエリアを参照していれば、
各スレッドがお互いに1つのワークエリアをぶっ壊しあう。
喪前さんのやり方では、そのパターンが検出できない。
むしろ、メモリリークしている方が複数のスレッドで異なるワークエリアを作成している、
つまり不完全ながらもマルチスレッド対応しているという見方もできる。
(実際どうかは知らん。メモリだけ確保して1つのワークを壊しまくってる可能性もある)
つか、なんでCreateThread()で試してるんだ?
試すまでもなく駄目なの分かり切ってるだろ。
_beginthread*()ならまだわからんでもないが・・・。
238:225
06/01/28 18:02:37
> 複数のスレッドで同時に1つのワークエリアを参照していれば、
> 各スレッドがお互いに1つのワークエリアをぶっ壊しあう。
マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
保証されているものだと思ってました。
_beginthread(ex) の説明を読む限り、メモリリーク問題以外については
何も記述されていません。
> つか、なんでCreateThread()で試してるんだ?
確認したかったのは、「A.EXE で作成したスレッド内で B.DLL 内の関数を
呼ぶことが出来るかどうか」だからです。
A.EXE は BCB5 で作成していて、B.DLL は VC6 で作成しています。
B.DLL 内の C ランタイムルーチンを使うのに、A.EXE の _beginthread(ex)
を使っても無意味なのは初めからわかりきっています。
また、>>235 では書きませんでしたが、3.の場合、C ランタイムルーチン
はスタティックリンクされてるので、やはり A.EXE の _beginthread(ex)
と B.DLL の _beginthread(ex) は全く別物です。
> 試すまでもなく駄目なの分かり切ってるだろ。
メモリリークという点だけ見れば、駄目とは言い切れないという結果に
なったと思うのですが。元々 DLL_THREAD_ATTACH/DETACH で解決し得る
問題だと思ってるので、この結果がおかしいとは思えません。
239:デフォルトの名無しさん
06/01/28 18:45:54
>>238
> マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
> 保証されているものだと思ってました。
思うのは勝手だけど、正しい使い方をしないと正しい挙動はしてくれないよ。
この場合、_beginthread*()を呼ばないと、「正しい挙動」はしてくれない。
なぜなら、Cランタイムをスレッドセーフにする肝心の処理を_beginthread*()がやるから。
ついでに言えば、問題はB.DLLだけの話ではなくて、A.EXEのランタイムに
何を使ってるか? というのも重要。にも関わらず、>>235でその点に
一切触れていない点からも、喪前さんの理解が足りないことが伺える。
240:225
06/01/28 20:18:06
>>239
> なぜなら、Cランタイムをスレッドセーフにする肝心の処理を_beginthread*()がやるから。
_beginthread(ex) と _endthead がやるのは、スレッドごとに必要なメモリ
の割り当てと解放を行うことですよね?
_beginthread を使わなかったせいで、ランタイムルーチンを呼び出し時に
そのスレッドではまだメモリが割り当てられてなかったなら、その場で動的に
割り当てれば問題ないでしょう。実際、動的に割り当ててると思うんだけど。
問題なのは、スレッドの終了を知ることが出来なくなるせいで、割り当てた
メモリを解放する機会が得られなくなり、その結果としてメモリリークが発
生する、ということではないの?
_beginthread(ex) を使わないことによって、排他処理的な問題が起こるとは
どこにも書いてないですよね?起こらないとも書いてないけど。
排他処理的な問題が起こると明記されてるのは、シングルスレッド版の
ランタイムを使った場合の方だけです。
マルチスレッド版の方では、メモリリークのことしか書いてないと思う
んですけど。
> ついでに言えば、問題はB.DLLだけの話ではなくて、A.EXEのランタイムに
> 何を使ってるか? というのも重要。にも関わらず、>>235でその点に
> 一切触れていない点からも、喪前さんの理解が足りないことが伺える。
A.EXE は BCB5 で作成、B.DLL は VC6 で作成と書いてます。
理解が足りないのは認めますが。
長文ばかりで申し訳ない。
241:デフォルトの名無しさん
06/01/28 20:54:27
とりあえず消えろ
242:225
06/01/28 21:09:14
>>241
真面目に質問してるつもりなんですが、そういうのが伝わらない
あたりが 2ch のイヤなところですね。
どこかにこの件に関してきちんと解説したウェブサイトなり書籍
があればご紹介頂きたかったですがね。
243:デフォルトの名無しさん
06/01/28 21:19:39
>>242
そういうのにいちいち気にしていたら駄目だよw
2chの使い方からまず学んだほうが有効に使えるかも。
当然俺のレスにもレスは要らないぞw(あってもいいけど
244:225
06/01/28 21:40:13
>>243
やっぱりそうですか。(^^;
>>235 の結果から、(この検証が正しければ)メモリリークに関しては
処理系依存ということになったわけだし、ドキュメント化されてるわけ
でもないようだから、結局のところ結論なんて出ないんだろうな…。
「A.EXE で作成したスレッドから B.DLL の関数を呼び出すとメモリリークする」
のだとすると、Susie プラグインとか、自分ではメンテナンス出来ないプラグイン
方式の DLL を使うアプリをマルチスレッド化するのは非現実的ということになっ
てしまうのか…。ほとんどの DLL は C ランタイムを使用してるだろうから。
一度作成したスレッドはアプリが終了するまで使い回すようにするしかないの
だろうか…。なんか納得行かないな。
245:デフォルトの名無しさん
06/01/28 22:06:40
Susieプラグイン使う様なサイズのアプリなら、
スレッドプール使えば"about 70-80 bytes"のリークなんて気にする必要ないのでは?
>>242
MSDNだろ。
246:241
06/01/28 22:09:50
マルチスレッドプログラミングをしたことのない房でも225のような真面目なやつを馬鹿にできるんだから
2chって憂さ晴らしに最適だよな。
247:デフォルトの名無しさん
06/01/28 23:06:33
>>231
248:デフォルトの名無しさん
06/01/29 01:07:13
>>244
真面目におかしなことばっかり言ってるから相手したくなくなるんだよ。
依存するのは処理系自体ではなくライブラリだし、
アンドキュメントな実装に依存したコードを書くのは無謀。
漏れが言えることは、
「EXE・DLLの両方で同じライブラリ使ってれば、相互に呼び合いしても問題ない」
「泥沼に足突っ込みたくなければ推奨されてるやり方を使え」
それだけ。普通にMSVCRT使えばいい。
それ以上のこと知りたいなら、AdvancedWindowsなりMSDNなりCRTのソースなり
自分で読んで勉強してくれ。スレでいちいち書けるほど単純な話でもない。
249:225
06/01/29 04:20:43
>>248
> 「EXE・DLLの両方で同じライブラリ使ってれば、相互に呼び合いしても問題ない」
DLL は他人が作ってるので自分でいじれないし、EXE は GUI の
関係上 BCB しか使えないので。
> 「泥沼に足突っ込みたくなければ推奨されてるやり方を使え」
EXE で作成したスレッドから DLL の関数を呼ぶ場合の推奨されてる
やり方とは?EXE/DLL ともに MSVCRT を使うことですか?
> AdvancedWindowsなりMSDNなりCRTのソースなり自分で読んで勉強してくれ
MSDN と CRT のソースは自分なりに熟読してみたつもりです。
CRT のソースから、>>235 の結果は予想通りでした。
でも、3.の結果は予想通りだけど納得行かない。
BCB5 の C ランタイムライブラリのバグと言うべきなんじゃないだろうか。
仕様で片付けていい問題ではないような…。
AdvancedWindows を読んでもう少し勉強してみます。
250:デフォルトの名無しさん
06/01/29 09:28:51
最後のはBorlandのドキュメント読まないと仕方ないでしょ。
使ったことないから、どういう事になっているのか知らないし、
それで仕様通りの利用かどうかもわからない。
いずれにせよ、サードパーティのDLL内で、
CreateThread()を多発してない限り、別に大きな障壁になることじゃないよね。
スレッドを多発する場合、スレッドプール使うのは鉄則だから。
251:デフォルトの名無しさん
06/01/29 18:37:53
>>237>>239
やなやつだなあ。
まじめに答えてる振り装ってるが不快なことこの上ない。
252:デフォルトの名無しさん
06/01/29 19:09:23
まあスレッドプログラミングなんてやってる香具師はそんな香具師ばっかりだから
253:デフォルトの名無しさん
06/01/29 19:30:17
だから日本はだめなんだよな
254:デフォルトの名無しさん
06/01/29 19:57:56
>>252
いっしょにすな!
255:デフォルトの名無しさん
06/01/29 21:20:17
URLリンク(support.microsoft.com)
の"static"の使い方は違和感あるなあ。
"thread local"ってことだよな。実際は生存期間が"dynamic"だし。
256:デフォルトの名無しさん
06/01/30 17:17:51
マルチスレッドでプログラムを作っているのですが、VisualC++6.0(SP6)でデバッグすると
しばらくするとフリーズしてしまいます。
フリーズというのは、VC++と実行しているEXEがまったく応答しなくなり、
さらにOSの反応がほとんどなくなる感じです。
ほとんどというのは、Alt+Tabぐらいは効くのですが、タスクマネージャーも起動せず
他のアプリも、しばらく動くのですがじきに応答がなくなります。
デバッグではなく、ただEXEを実行した場合は普通です。
OSはWindowsXPHome SP2で、まあ標準的な環境だと思います。
1つ怪しいのといえば、NortonAntiVirusですが、これに関しては
ほぼインストールしたてのWin2000SP4のマシンでやっても同じような現象が
起こったので、他のアプリが邪魔している、というわけでもなさそうです。
それなりに長いソースなので、同様の問題が発生する簡単なソースをコピペします。
257:256
06/01/30 17:18:38
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
char* szClassNme = "aaa";
DWORD WINAPI thread_proc(LPVOID param)
{
int i;
while(1)
{
i++;
Sleep(10);
}
}
258:256
06/01/30 17:19:29
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS WClass;
HWND hWnd;
DWORD tid;
if (!hPreInst) {
WClass.style= CS_HREDRAW | CS_VREDRAW;
WClass.lpfnWndProc= WndProc;
WClass.cbClsExtra= 0;
WClass.cbWndExtra= 0;
WClass.hInstance= hInstance;
WClass.hIcon= NULL;
WClass.hCursor= LoadCursor(NULL, IDC_ARROW);
WClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
WClass.lpszMenuName= NULL;
WClass.lpszClassName= szClassNme;
if(!RegisterClass(&WClass))
return 0;
}
hWnd = CreateWindow(szClassNme, "aaa", WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX,
100, 100, 200, 200, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
259:256
06/01/30 17:24:07
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return 0;
}
260:256
06/01/30 17:30:36
thread_procの、while(1)のところにブレークポイントを設定し
F5を連打し何回かループさせると、いずれ固まります。
ひょっとしてプログラムに何か原因があるのでしょうか?
デバッグがままならないとなると開発が非常に困難です。
261:256
06/01/30 20:19:40
WinXPで、ウィンドウズキー+Lで、ユーザーを切り替ることはできたので
別のユーザーからMSDEV.exeを強制終了すると、一応復帰できることが分かりました。
しかし、依然として非常に困っています。
もし以前こんな現象に見舞われたけど、こうして直したよ、とか
ここをこうしたらいいんじゃないの?っていうのがありましたらぜひ教えていただきたいです。
262:デフォルトの名無しさん
06/01/30 20:32:17
osの再インストールしても直らなかったという、ほろ苦い思い出があるよ。
263:256
06/01/30 21:32:25
>262
その後は結局どうなりました?
ひょっとしてマルチスレッドのデバッグは、VC++6.0でできないっていうのが
「仕様」なんでしょうか?
264:デフォルトの名無しさん
06/01/30 21:52:07
Windowsを2000にするか、VisualStudioをバージョンアップしませう
265:256
06/01/30 22:01:27
>264
Windows2000でもなりました。
VisualStudioをバージョンアップですか.... 高かったんですよね。
266:デフォルトの名無しさん
06/01/30 22:26:40
>>256
私も Windows2000 から XP にアップグレードしてから似たような
現象が発生するようになりました。
VC++6.0 と BCB5 でそうなっていて、どちらもマルチスレッド
アプリケーションでなくても発生します。
なんか Window メッセージの送受信の応答がシステム全体でとてつもなく
遅くなる感じですね。バックグラウンドで音楽とか流していても、音楽は
普通に流れますが、ウィンドウの切り替えとかがものすごく遅くなります。
完全なフリーズじゃないだけに、諦めて電源を落とそうにも、落とすタイ
ミングに困ってしまうというか。
URLリンク(www.wg7.com)
これと似たような症状なんですが、私は試していません。言語バーが
使えなくなるのも困るので。
結構頻繁に起こるので辛いのですが、起こらないときは起こらないので、
そういうものだと思って諦めています。
267:225
06/01/30 22:43:46
_beginthread(ex) の説明のところに、CreateThread だとメモリリークして
しまう C ランタイム関数の一覧でも書いてあれば良いんですけどね。
URLリンク(support.microsoft.com)
には malloc とか fopen でもメモリリークするようなことが書かれてるけど、
実際に試してみると、VC6/BCB5 どちらの場合もメモリリークしてるようには
思えないです。
ここに書かれてないものでは、rand() を使うとメモリリークしますね。
今回の呼び出しの結果が前回の呼び出しに依存するようなタイプの関数は
全滅なんでしょうね。
268:256
06/01/30 22:55:37
>266
確かに今まで他のプログラムを組んでいるときにそういうことはありました。
しかし、今回はそれとはちょっと違うように思えるのです。
一度固まると、少なくとも20分ぐらいは待ってみたのですが復帰しませんでした。
しかも、ほぼ毎回起こります。
上のソースに何か問題点があるのでしょうか?
ウィンドウメッセージに応じて処理をするスレッド(最初に起動されたときのもの)
別に他の計算をするスレッドを別に作っています。
競合が起こっているのかと思い、上のような簡単な簡単なソースを書いてみたのですが
あれでも必ずといっていいほど起こります。
ちなみにWindowsMeでも起こりました。家のPC全滅です..
269:266
06/01/31 00:34:55
最初は自分が書いたプログラムに原因があると思ってたのですが、
Web 上にある他人が書いたもののいくつかを自分の環境でコンパイル・実行
してもそうなるので、環境によるものだと思って諦めることにしました。
Windows2000 では問題なかったので、256 さんと私とでは状況が
少し異なりますね。マルチスレッドアプリケーションでなくても
発生しますし。お役に立てなくてすみません。
270:デフォルトの名無しさん
06/01/31 01:33:38
オレもよくなる。ステップ実行しているとなんでもないところで固まってCtrl+Alt+Delをやって再起動とかやるが
まったく動かず、次にAlt+Tabで悪あがき。選択した窓から順に固まる。
最後電源長押し、するとmsdev.exeを終了しています、かなんかがでて、msdev.exeが終了するとほかもサクサク終わる。
もちろんまったく終わらないでそのまま固まることもある。
DLLで提供される関数をステップオーバーしたときに出るとか、なんか最初はそんなことを思っていたけど
そうでもないらしい。
271:デフォルトの名無しさん
06/01/31 09:31:42
Windowsのスケジューラ糞馬鹿だから
タスクマネージャでMSDEV.EXEのプライオリティ上げろ。
272:256
06/01/31 21:11:22
VisualStudio .NET 2003を入れてデバッグしてみたところ、簡単なものは
ほとんど固まらなくなりましたが(とはいえ、ごくたまに固まります)
開発しているプログラムは依然として固まるようです。
いまいちすっきりしないのですが、あまりこの問題にかまっている時間的
余裕も無いのでデバッグ時のみシングルスレッドで動くようにして
場当たり的な解決をすることにしました。
幸運にもあまり修正せずにすむに済みました。
依然として自分のプログラムに問題があるのかという不安はのこりますが...
266さんをはじめ、皆様、様々な情報提供ありがとうございます。
よくあることのようなので、少し安心しました。(していいのか!?)
273:デフォルトの名無しさん
06/01/31 21:27:49
>263
imeだか関係の問題だったはず。
URLリンク(ww1.enjoy.ne.jp)
の、マルチスレッドの注意点の項を参考にしてみては?
私は効果なかったんですが・・・
274:デフォルトの名無しさん
06/02/01 01:56:10
257のコードで何にも問題は出なかったぞ。
F5押しっぱなしでも固まるどころか快調そのもの。
Dual Pentium III 1GHz, NT4.0 VC++ 6.0+Sp5
275:デフォルトの名無しさん
06/02/03 16:12:33
>>256
デバッグモードでなぜかおかしくなるというWin個体は確かにある。
どうしようもない。マシン変えろ
276:sage
06/02/04 00:23:14
VB6.0でActiveX DLLを使用し、マルチスレッドを実現できるという噂を聞いたのですが
本当ですか?
でもイメージが掴めない・・・
VBでActiveXコンポーネント「A」を呼び出し
↓
A作成→A何らかの処理
↓
VBの処理←A処理終了
↓
VB次の処理
って感じでマルチスレッドとは違う気がするんですが・・
もし本当であれば、どなたか参考になるサイトをご教授頂けませんでしょうか
277:デフォルトの名無しさん
06/02/04 01:43:21
URLリンク(search.yahoo.co.jp)
278:デフォルトの名無しさん
06/02/04 08:38:15
>>276
DLLの中はC++で書けばなんでもやり放題なんじゃね?
DLLの中でクリートスレッド
279:デフォルトの名無しさん
06/02/04 09:02:03
>>278
クリートスレッドってなに?
280:デフォルトの名無しさん
06/02/04 09:39:29
CreateとDeleteの合成語だろ
スレッドを作ったら自分で閉じろってことだ
281:デフォルトの名無しさん
06/02/04 12:14:10
>>276
ActiveX のコンポーネントとして作成した DLL/EXE が
スレッドセーフだ、ってだけじゃね?
282:デフォルトの名無しさん
06/02/04 12:20:51
何をしたいのかしらんが
COMのスレッドは楽しいぞ
283:デフォルトの名無しさん
06/02/06 19:46:27
CreateThreadをクリートスレッドって読んだんだろ。
馬鹿みたいだが。
284:デフォルトの名無しさん
06/02/11 07:40:21
もう二日も考え込んでるんですが解決しないんで質問です。(うう、マジで目と頭が痛い…。)
基本的に生産者消費者問題なんですが
Aが物を作るとBに渡し、Bが物を作るとCに渡し、Cが物を作るとDに渡す、というように
複数の生産者/消費者のベルトコンベヤーでの流れ作業を想定しています。
で以下のように組んでみたんですが、
今度はB自身が消費したことをB自身に知らせなくてはならなくてこんがらがってきました。
public class Main
{
public static void main(String args[]) {
ConveyerBelt stationAB = new ConveyerBelt();
ConveyerBelt stationBC = new ConveyerBelt();
ConveyerBelt stationCD = new ConveyerBelt();
Worker producerA = new Worker(stationAB);
Widget consumerB = new Widget(stationAB);
Worker producerB = new Worker(stationBC);
Widget consumerC = new Widget(stationBC);
Worker producerC = new Worker(stationCD);
Widget consumerD = new Widget(stationCD);
producerA.start();
consumerB.start();
producerB.start();
consumerC.start();
producerC.start();
consumerD.start();
}
}
ConveyerBelt()バッファーが三つというのは正しいと思うんですけど
スレッドはABCDの四つだけ作ればいいんでしょうか?どなたかご教授下さい。
285:284
06/02/11 07:43:18
ちなみにセマフォは「なし」の方向でお願いします。
286:デフォルトの名無しさん
06/02/11 07:47:19
日本語で質問してください
287:デフォルトの名無しさん
06/02/11 08:44:23
>>284
Chain Of Responsibility パターンはもう検討済みなの?
288:デフォルトの名無しさん
06/02/11 10:21:28
>>284
4つじゃないとダメなわけもないし、好きに作ればいい
289:デフォルトの名無しさん
06/02/11 12:09:10
各々理由を書いてね。
> 今度はB自身が消費したことをB自身に知らせなくては
> ならなくて
> ちなみにセマフォは「なし」の方向でお願いします。
290:デフォルトの名無しさん
06/02/11 18:57:50
>>289
正確厨、規格厨、口先厨の予感。現状提示されている情報から
回答が思いつかなければ、その問題に対する類似性や経験則
など思い当たるところが無いっつーことだろ。
全部の情報が分からないとコミュニケーションできないような
応用力無しやつは黙ってろ
291:デフォルトの名無しさん
06/02/11 19:56:02
>>9
Double Checked Lockingに追加
Scott Meyers & Andrei Alexandrescu
"C++ and The Perils of Double-Checked Locking (II)"
URLリンク(erdani.org)
付録に"volatile: Brief History"あり。
Douglas C. Schmidt & Tim Harrison
"Double-Checked Locking
An Optimization Pattern for Efficiently Initializing and Accessing Thread-safe Objects"
URLリンク(www.cs.wustl.edu)
292:デフォルトの名無しさん
06/02/11 21:48:09
>>290
エスパー以外は黙れと。
293:291
06/02/11 22:33:21
せっかく流れ切ったのに…
294:デフォルトの名無しさん
06/02/11 22:58:43
>>290
やんわりと、「設計がおかしいんじゃないか?」と言われてるんだよ。
まあ、もうまともな回答は期待できないだろうからどうでもいい話だが。
295:284
06/02/12 01:45:30
ご迷惑をお掛けしております。m(__)m
>>287
そんな概念があったんですね。というくらいなので検討済みではないです。
検索してみていくつかサイトを見つけたのでもう少し読んでみます。
分からなければまた質問します。それと
if (Thread.currentThread() == "Thread[Thread-0,5,main]")
System.out.println("I am the Worker A.");
のようなチェックを入れたいんですが、そんな比較はできないみたいです。
左辺値はどんな感じにすればいいんでしょうか?
これができれば、一つ一つ鎖をつなげていける気がするんですが。
>>288
逆を言うと「4つでもできる」ということですか?
>>289
現状を話しますと
Aから渡された物をB自身が処理(消費)してもないのに
(いや、時にはAから物を渡されてもないのに)
Bは勝手に生産を始めてしまいます。
ですから現在はA-B間、B-C間、C-D間のみで同期がされてます。
それと、やっぱりセマフォアは「あり」でもいいです。
296:デフォルトの名無しさん
06/02/12 05:05:21
ここでは綺麗でも汚くても叩かれますYOW
297:デフォルトの名無しさん
06/02/12 05:06:03
誤爆した スマン...
298:デフォルトの名無しさん
06/02/12 07:55:32
>>294
その「やんわりと」の部分が他人をイラつかせるんだよ。現実でも
相当にいやみな人間だろう
299:デフォルトの名無しさん
06/02/12 08:00:36
>>292
そこまで行間が読めないようだと生きるのに苦労してないか?
300:デフォルトの名無しさん
06/02/12 08:14:33
>>299
292は皮肉で言っただけだから、普段は別段苦労はしてないな。
301:デフォルトの名無しさん
06/02/12 11:03:26
この業界、日本語の喋れない奴ばかりだからエスパー能力は必須だよね
低級エスパーだから日々苦労してるよ
302:デフォルトの名無しさん
06/02/12 11:38:10
エスパーってほどか? そうじゃなくてだな、俺の言いたいことはだ、
類似の問題を経験していたら回答が思い浮かぶだろ。素直に
それ書いてやりゃいいんだ。お前らだって今まで誰かに教えて
もらったり助けてもらったことあるだろうに。
それを忘れてくだらねー皮肉や、重箱の隅をつつくようなまぜっかえしを
親切を装ってやるようないやらしいことすんなよ。ナサケナス
303:デフォルトの名無しさん
06/02/12 11:48:06
別に2chで教えようと混ぜっ返そうとどっちでも構わんと思うのだけど。
まぁ、ヒントだけ貰った方がいい場合と答丸ごと貰った方がいい場合があるのでどっちがいいとも言えないしね。
漏れはここのスレでは教えることも教わることも少ないけど、この板全体では教わることより教えることのほうが多くなるようにしている積もりだがね。
混ぜっ返したり揶揄したり誘導したりも多いけどw
304:284
06/02/12 12:23:35
で、あのー・・・
305:デフォルトの名無しさん
06/02/12 12:28:35
生産者消費者問題くらい、標準的なテキスト読んで自分でやれ
306:284
06/02/12 12:37:41
テキストには生産者消費者が一対一の例しか載ってないんですよ。
こんなに真剣に質問してるのになんでこんな目に遭うんだ…
世の中絶対におかしい。
307:284
06/02/12 12:38:49
丸投げでもなく真剣に書いてるのに…もう馬鹿馬鹿しくて泣けてきた…もういいです。
308:デフォルトの名無しさん
06/02/12 12:57:25
なんで、consumerBとproducerBが別オブジェクトなわけ?
ふつうは入口と出口のある1つのオブジェクトとして考えるでそ?
309:デフォルトの名無しさん
06/02/12 13:03:48
お前らかわいそうだから教えてやれ。おれは良く分からないのでパス。ごめん
310:デフォルトの名無しさん
06/02/12 13:05:39
レベル1エスパーだけど、
>>284
>> ConveyerBelt()バッファーが三つというのは正しいと思うんですけど
>> スレッドはABCDの四つだけ作ればいいんでしょうか?どなたかご教授下さい。
唯一の正解があると思ってるのか?好きにつくれよ
311:デフォルトの名無しさん
06/02/12 13:06:34
>>306
質問する相手を間違えているだけだろう?
世の中がおかしいのではないと思う。
312:デフォルトの名無しさん
06/02/12 13:11:45
普通はレスの付き方を見て、質問の仕方が悪いと思うんだけどね
313:デフォルトの名無しさん
06/02/12 13:17:51
>>284
漏れも>308の言うとおりだと思う。
つか、めっちゃ単純な問題だと思ってたから
まさかconsumerBとproducerBが別だと思ってなかったw
あらためてソース見直してみてビックリした。
> ですから現在はA-B間、B-C間、C-D間のみで同期がされてます。
それでいいんじゃないの?他に同期取らなきゃいけないの?セマフォもいらんと思うけど。
314:デフォルトの名無しさん
06/02/12 13:30:26
>>313
> 他に同期取らなきゃいけないの?
知りもしないのに、
> セマフォもいらんと思うけど。
云うな(w
315:デフォルトの名無しさん
06/02/12 13:43:39
うん、ごめん。よくわかってなかったわ。
最初ConveyerBeltの作り疑ってたもんな。
危うく恥かくとこだった。
316:289
06/02/12 13:51:11
俺も、>>308 に同意。
だから、
> 今度はB自身が消費したことをB自身に知らせなくては
> ならなくて
は、何か勘違いしてんじゃないかと思って、>>289 を書
いてる。はじめのうちは、(俺も含めて) 結構とんでもな
い勘違いをすることがあるから、別にそれがおかしいとは
思わないけど、何を考えてるかわからんと情報を提供して
あげることもできないから。
あと、>>306-307 が本人かどうか知らんけど、「真剣に
質問」したのにまともな答えが返ってこないと言うが、
匿名掲示板に質問すること自体が既に「真剣に質問」して
いるとは言えない。回答する方は、あくまでも知ったかし
たいか暇つぶしか昔の恩を返したいかなんだから、「真剣
に向き合え」とか言われたら、「なんちゃ、それ。」で無
視されるのがオチ。
この板の人は基本的に親切だから、嘘は余り書いてない。
>>290 みたいな雑音を飛ばしてよく読めば、きちんと
ヒントは書かれているから、自分でググルなりすればいい。
そのものズバリの答えが欲しいなら、本を買うなり学校に
通え。
317:デフォルトの名無しさん
06/02/12 14:14:03
実質何も答えていないのを繰り返してるだけじゃね?
318:デフォルトの名無しさん
06/02/12 14:19:02
答える側が堂々巡りするケースのほとんどは、
質問がいい加減なことに起因する。
319:デフォルトの名無しさん
06/02/12 15:40:49
320:289
06/02/12 15:47:02
>>317
まあ、確かにそのものズバリの回答は無いけど、>>287,
>>308 あたりは、充分ヒントになりうると思うが。
個人的見解として、このヒントを基に自分で勉強するぐら
いでないとマルチスレッドのプログラミングはできないと
思う。
321:デフォルトの名無しさん
06/02/12 19:56:19
変なところで改行するなよ
醜い
322:デフォルトの名無しさん
06/02/14 13:30:16
久し振りに来てみたが、相変わらず、このスレは知ったか馬鹿が多いな。
とりあえず>>288、>>310、>>311あたりの馬鹿どもはこのスレいても邪魔だから消えろ。
もう>>284はいないと思うが俺なら
public class Main
{
public static void main(String args[]) {
ConveyerBelt NULL = new ConveyerBelt();
ConveyerBelt stationAB = new ConveyerBelt();
ConveyerBelt stationBC = new ConveyerBelt();
ConveyerBelt stationCD = new ConveyerBelt();
Worker workerA = new Worker(NULL, stationAB);
Worker workerB = new Worker(stationAB, stationBC);
Worker workerC = new Worker(stationBC, stationCD);
Worker workerD = new Worker(stationCD, NULL);
workerA.start();
workerB.start();
workerC.start();
workerD.start();
}
}
とやる。ConveyerBeltクラスん中ではinとoutの二つのbufferを作ってやれ。
323:デフォルトの名無しさん
06/02/14 23:01:34
>>322
> ConveyerBelt NULL = new ConveyerBelt();
> ConveyerBeltクラスん中ではinとoutの二つのbufferを作ってやれ。
馬鹿ジャネーの。
324:デフォルトの名無しさん
06/02/15 00:03:38
>>323
自分の事を良く解ってるじゃないかw
325:デフォルトの名無しさん
06/02/15 00:15:31
俺も
> ConveyerBeltクラスん中ではinとoutの二つのbufferを作ってやれ。
は意味わかんねえ。ConveyerBeltなのに何か処理でもするの?
326:釣りだったのかも...。
06/02/15 01:13:37
>>325
多分、in と out の buffer を取り持つ ConveyerBeltSub
を作るんだよ。
もちろん、その中には buffer が二ついるから、更に
ConveyerBeltSubSub を作って...。(w
# >>322 = >>324 は、基礎から勉強しなおした方がいいぞ。
327:デフォルトの名無しさん
06/02/15 01:48:57
buffer1個でいいでしょ
328:デフォルトの名無しさん
06/02/15 03:43:24
どうでもいいけどなんで4つとも別スレッドで独立して動かす必要がるわけ?
全体としてどんなことをしたいのか今一想像がつかん。
329:デフォルトの名無しさん
06/02/15 15:13:36
あらあら、もう一人馬鹿↑が来た
お前、流れ作業って言葉聞いたことあるか?
330:デフォルトの名無しさん
06/02/15 15:20:00
>Aが物を作るとBに渡し、Bが物を作るとCに渡し、Cが物を作るとDに渡す、というように
>複数の生産者/消費者のベルトコンベヤーでの流れ作業を想定しています。
>>327
お前の読解力は小学生以下か?
buffer一つで出来るもんならやってみろ、馬鹿。
出来ないんならもう来るなよ、ここではお前は邪魔なだけだから。
331:デフォルトの名無しさん
06/02/15 16:06:16
パイプ1個あたりバッファ1個の意味で言った
言葉足らずというか全然意味が通らないねスマソ
332:デフォルトの名無しさん
06/02/15 18:06:14
Java よく知らんのだが、これは要するに
4つのスレッドを3つのキューで繋ぎたい、って「だけ」の話?
333:デフォルトの名無しさん
06/02/15 18:34:54
YES
334:デフォルトの名無しさん
06/02/15 21:04:57
>>329
いやそうじゃなくてどんな処理で4スレッドの流れ作業なんて必要になるのか
想像がつかんのだ。
335:デフォルトの名無しさん
06/02/15 23:29:55
マルチ商法ですた
336:デフォルトの名無しさん
06/02/15 23:46:26
そんなもの想像つかなくていい。
質問に答えりゃそれでいいんだ
337:デフォルトの名無しさん
06/02/16 01:22:58
関連する複数のタスクを回す場合は、個別に分けずに
スレッドプールでまとめてやるのがいいんじゃないの?
やろうと思えばExecuterServiceでも似たようなのできるけど。
□ タスク側
1. 自身のタスク終わったら次のCallableをsubmit()する。
2. 途中のタスクの戻り値としては次のFutureを返す。
3. 最後のタスクは流れ作業全体の値を返す
□ 呼び出し側
1. ExecuterServiceに最初のCallableをsubmit()する。
2. Futureのget()がFutureを返した場合は置き換えてループする。
3. Future以外が返って来たら全タスク完了。
ただ、Callable中で次のタスクをsubmit()すると、バウンド形式なQueueで
最大スレッド数に制限が付いてるとデッドロックの可能性があると思われ。
これはExecuterServiceを流れ作業の数だけ作れば回避できそうかな?
338:デフォルトの名無しさん
06/02/16 01:58:33
>>333
㌧楠。
たったそれだけの事で、こんだけ盛り上がれるなんて
なんの病気なんだ…
>>334
それを実現する手段を知るためじゃね?演習問題みたいな。
339:デフォルトの名無しさん
06/02/16 09:57:05
>>332
たぶんそう。それなのにbuffer二つとか言い出す奴もいて…
そもそも質問があれだし。
340:デフォルトの名無しさん
06/02/17 12:51:20
みんなコロンブスの卵って知ってる?
「コロンブスの卵」は、「誰にできることでも、最初にするのが難しい」という意味で使われる。
1492年にアメリカ大陸(西インド諸島のサンサルバドル島といわれている)を発見したことで有名なコロンブス。
その功績を祝う晩餐会で、ある男が言った「西へ西へと航海して陸地に出会っただけではないか」と言った皮肉に
対して、コロンブスは卵を取り上げ、「この卵を卓の上に立ててごらんなさい」と言った
だれも立てられないのを確認するとコロンブスは、卵のおしり(気室のある鈍端部と思われる)を食卓でコツンとた
たいて立てて言った。「人がした後では何事も簡単です」
>>332
で、その「だけ」の話を理解できなかったのはどこの馬鹿だったっけ?( ´,_ゝ`)プッ
341:デフォルトの名無しさん
06/02/17 13:03:35
なにこの馬鹿…
342:デフォルトの名無しさん
06/02/17 13:13:45
ああ!この↑馬鹿か、その「だけ」の話を理解できなかったのは!
343:デフォルトの名無しさん
06/02/18 00:44:40
文章から頭の悪さが滲み出ている。
344:デフォルトの名無しさん
06/02/18 12:29:01
↑「だけ」の話を理解できなかったのが相当悔しかったんだね。( ´,_ゝ`)プッ
345:デフォルトの名無しさん
06/02/18 16:24:11
なんか雰囲気が悪くなってきたな。
元に戻そうぜ。
これって
Aの生産量≦Bの生産量≦Cの生産量
だよね?でないとCとかDとかが結構待たされるんじゃないのかなーと。
346:デフォルトの名無しさん
06/02/18 21:50:29
↑何もわかってない奴の典型だな!
347:デフォルトの名無しさん
06/02/18 22:38:57
と、必死。
348:デフォルトの名無しさん
06/02/18 23:57:11
荒している馬鹿は、>>322の阿呆レスした奴?
349:デフォルトの名無しさん
06/02/19 03:12:23
ここにいるのは馬鹿ばっかだな
350:デフォルトの名無しさん
06/02/19 03:15:52
>>345
ふいんき(←なぜか変換できない)戻そうと必死なのは分かるが
流れ作業なので
Aの生産量=Bの生産量=Cの生産量
351:332=338
06/02/19 03:40:54
荒らしの相手はやめようや。
>>334
今思い出したが、以前C++ on Windowsで似たような構成にしたことあったわ。
その時は通信スレッド×20→データベーススレッド×2→印刷スレッド×1だったが
キューとミューテックス(各1)で小さいクラス作ったような覚えが。
352:デフォルトの名無しさん
06/02/20 04:08:06
>>350
なんで?
極端な話、Aが2つの整数を流してBがそのxorを流したら半分じゃん。
まぁ別にそんなのはどうでも良くて、
単に4つスレッドを作らなくちゃいけない状況を想像して見たかっただけ。
邪魔してすまん。
353:デフォルトの名無しさん
06/02/20 21:16:12
10メガくらいのメモリをコピー(memcpyとか)するときに、
領域を分割してマルチスレッドにしたら速度上がる?
マルチコアとかマルチスレッディングなら上がるかな?
354:デフォルトの名無しさん
06/02/20 22:57:06
memcpy()だったら変わらない希ガス
fread()とかで、あるスレッドでHDDからデータ読み込み中に、
前回読み込んだデータ解析を行うとかだったらスループットはあがると思う。
355:デフォルトの名無しさん
06/02/21 11:30:13
>>353
CPUが速ければ、
キャッシュを含めたバスシステムがボトルネックになるまでは上がる。
システム依存だから自分のターゲットにしているヤツで試してみて。
356:353
06/02/22 08:10:39
ありがとう。
でも本当はそんなメモリコピーしない設計にするのがいいんだよなorz
357:デフォルトの名無しさん
06/02/22 21:31:45
じゃあ、なんでそんな設計にならざるを得なかったのか、説明してみればいいじゃない。
メモリ参照だけで済むアルゴリズムを誰かが教えてくれるんじゃない?
358:デフォルトの名無しさん
06/02/22 22:06:40
writeで例外起こすようにしてcopy-on-writeだ
359:デフォルトの名無しさん
06/02/23 02:58:53
設計したのは赤の他人。
ワタシはメンテ担当(涙)
360:デフォルトの名無しさん
06/02/23 17:25:34
>>359
その赤の他人よりも上手に設計できたとおもう?
361:デフォルトの名無しさん
06/02/24 00:01:14
何このウスラ馬鹿な突っ込み
362:デフォルトの名無しさん
06/02/26 01:05:49
>>359
設計思想もわからん個所を、色々チューニングしようとしてるの?
悪いことは言わないから「やめとき」。
363:デフォルトの名無しさん
06/02/26 01:08:10
仕事じゃしょうがないよな。
364:デフォルトの名無しさん
06/03/03 07:10:31
UNIXでC++なんですが、URLリンク(d.hatena.ne.jp) ここに載っている、
スレッドローカルストレージを使ったシングルトンの実装って安全でしょうか?
だいたいこんな感じになってます。
public:
static T& getInstance(void) {
static __thread T* tsd_instance = 0;
if (!tsd_instance) {
tsd_instance = getInstance_();
}
return *tsd_instance;
}
private:
static T* getInstance_(void) {
boost::mutex::scoped_lock lk(m);
if (!instance) {
instance = new T;
}
return instance;
}
365:デフォルトの名無しさん
06/03/03 12:00:38
ISO C++の範囲内でポータブルな実装はないんだ。
>>291を読め。
366:デフォルトの名無しさん
06/03/03 23:44:47
>>364
安全ですよ。
getInstance_(void) が既に安全なわけで、
tsd_instance の方は覚えとくだけで、
かつ単一スレッドからしか参照されないので。
メモリモデルの問題については、
たぶんscoped_lock の解放でメモリバリアも処理されるんでしょう。
(pthread のドキュメント呼んでないのであてずっぽう)
367:デフォルトの名無しさん
06/03/04 22:28:46
>365
364はDCL関係ないじゃん
368:デフォルトの名無しさん
06/03/04 22:52:17
>>366
POSIXではmutexの開放はメモリバリア。
369:デフォルトの名無しさん
06/03/05 00:20:02
>>364 例の URLリンク(www.nwcpp.org)
の最後のほうに
> Replace global singletons with per-thread singletons:
> - Each can use thread-local storage.
> -- Threading concerns during initialization thus vanish.
> - But now there are multiple "singletons."
と書いてあって、TLSを364のようには使ってないのが気になります。
一方、
URLリンク(www.cs.umd.edu)
でDoug Leaさんが364方式のTLSの使い方に文句を言っていない(条件
付きながら)ので大丈夫な気もします。まぁ、かなり昔のML投稿ですけど
ね・・。
さて真相は?
370:デフォルトの名無しさん
06/03/06 16:07:01
>>340
普通の卵は比較的簡単に立つよな。表面に凹凸があるから。産みたてほど立ち易い。
・・・コロンブスは卵をツルツルに磨き上げていたに違いない。
371:デフォルトの名無しさん
06/03/06 17:35:06
>>370
まあまあ。
コロンブスもギャグで言っただけなんだから許してやってくれ。
372:デフォルトの名無しさん
06/03/06 19:33:03
後世の作り話ですから。
まあ>>340は底抜けの馬鹿だけど。
373:デフォルトの名無しさん
06/03/07 14:35:11
ゆで卵にして高速で回せば立つよ。
まあ>>372は底抜けの馬鹿だけど。
374:デフォルトの名無しさん
06/03/07 14:57:53
盛り上がっているところ、横から突っ込んでスマンけど。
生卵を立てるには塩をごく少量盛って、その上に立てて、横から
息をゆっくり吹きかけて塩を飛ばすといいという話を聞いた。
とかいう本当にどうでもいい話をマルチスレッドスレでする
自分は底抜けの馬鹿ですw
375:デフォルトの名無しさん
06/03/07 19:27:05
つまり塩スレッドに卵スレッドをロックさせれば桶?