マルチスレッドプログ ..
[2ch|▼Menu]
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
d楠。
たったそれだけの事で、こんだけ盛り上がれるなんて
なんの病気なんだ…

>>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は底抜けの馬鹿だけど。


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5358日前に更新/278 KB
担当:undef