1 :
デフォルトの名無しさん :
2001/08/09(木) 17:31 マルチスレッドプログラミング相談室
2 :
デフォルトの名無しさん :2001/08/09(木) 17:33
ブロードキャストプログラミング相談室
3 :
デフォルトの名無しさん :2001/08/09(木) 17:52
ピーコとおすぎのファッションプログラミング相談室
淀川長治の冥界ホモジニアス環境プログラミング相談室
5 :
デフォルトの名無しさん :2001/08/09(木) 19:02
g++でマルチスレッドなプログラムを書くときにオススメのクラスライブラリありますか?プラットホームはUNIX全般、 コーディング目的は暇潰しです
環境に依存しないネタでスレッドプログラミングについて 語りたいならJavaやC#やるのが手っ取り早い。 環境依存ならWindowsが一番楽しいかも
9 :
無党派さん :2001/08/09(木) 19:47
10 :
デフォルトの名無しさん :2001/08/09(木) 22:25
MT-safeがしっかりしているライブラリが揃った環境って どういうのがありますか?
フリーのOSで一番pthreadがちゃんと実装されてるのって何? まさかLinuxの分けはないよね?
フリーの定義によってはSolaris?(笑
13 :
デフォルトの名無しさん :2001/08/09(木) 22:57
14 :
デフォルトの名無しさん :2001/08/09(木) 23:04
>>11 FreeBSD3.xと、Linux2.0.xではLinuxの方がよかった。
IRIXもわりとしっかりしてた。
NetBSD、OpenBSDは全く知らん。
スレッドまわりは、OS・カーネル・ライブラリ(libcとか)での差が激しいので、
環境の違いが少ないWin32プラットホームが一番やりやすい。
やっぱりSolarisですか・・・
16 :
14 :2001/08/09(木) 23:08
>>15 猛烈に同意。でも、Solarisはカーネル以外の部分を含んだシステムと
しては、使いづらい。
17 :
デフォルトの名無しさん :2001/08/09(木) 23:09
fork !!!!
18 :
デフォルトの名無しさん :2001/08/09(木) 23:11
Win32の話ですが InterlockedIncrement()はなんでガードしないと行けないんですか? 4バイトのインクリメントならアセンブラでincとかになるから、 ロックはいらない気がするんですが。
ちなみにLinuxのcloneって関数、あれforkなんでしょ?
20 :
デフォルトの名無しさん :2001/08/09(木) 23:29
>>18 たぶんX86以外のプラットホームで問題が起きるからでしょ。
X86ならメモリの値をインクリメントする命令があるけど
RISCはそんな複雑な命令なさそうだし。
winbase.hでもInterlockedIncrement()の定義の前は
---
#if (defined(_M_MRX000) || defined(_M_ALPHA) || (defined(_M_PPC) && (_MSC_VER >= 1000))) && !defined(RC_INVOKED)
---
ってなってるし。
21 :
デフォルトの名無しさん :2001/08/09(木) 23:55
一番揃ってるのはwin32っぽいですね。 unixだとスレッド使うよりpiped forkやIPC使ったほうがよさげな気がしませんか。
22 :
デフォルトの名無しさん :2001/08/10(金) 00:03
非Win32な環境でスレッドローカル変数を効率的に扱うにはどうすればいいでしょうか? pthread_[gs]etspecificなんていちいちやってられないし…
windowsはプロセス起動がunixに比べて重過ぎるから、 仕方無くスレッドが発展したらしい>21
forkがcloneで実装されてるってだけですね
25 :
デフォルトの名無しさん :2001/08/10(金) 02:55
posixあげ
26 :
無党派さん :2001/08/10(金) 03:01
>>19 > ちなみにLinuxのcloneって関数、あれforkなんでしょ?
メモリ空間とか共有するリソースがあるfork。BSDのrforkに似ている。
で、threadは特殊なprocessだから、
signalのsemanticsがpthreadとちょっと違う。ただ違うのはここだけ。
linuxthreadsのREADMEより、
- Signal handling does not fully conform to the Posix standard,
due to the fact that threads are here distinct processes that can be
sent signals individually, so there's no notion of sending a signal
to "the" process (the collection of all threads).
More precisely, here is a summary of the standard requirements
and how they are met by the implementation:
(略)
*BSDよりはPOSIX conformance度は高い。
27 :
無党派さん :2001/08/10(金) 03:04
>>21 > 一番揃ってるのはwin32っぽいですね。
そんなことはない。スケジューラとか非常に貧弱。
POSIX 4相当(準拠でなくてもいいが)には全然足りない。
28 :
無党派さん :2001/08/10(金) 03:09
>>22 > 非Win32な環境でスレッドローカル変数を効率的に扱うにはどうすればいいでしょうか?
> pthread_[gs]etspecificなんていちいちやってられないし…
これは必要な時に使うもので、必要でなければ使わなければ良い。
どう利用するかによって、どうすればいいかは変わってくるから、
これ以上答えられない。
29 :
デフォルトの名無しさん :2001/08/10(金) 03:18
>>24 え?それはぎゃくじゃない?
sys_cloneからdo_fork呼んでるように見えるけど。
arch/i386/kernel/process.cなんか見ると。
おれの勘違いだったらごめん
30 :
デフォルトの名無しさん :2001/08/10(金) 08:54
>>27 スケジューラって具体的に何を指してますか?
あと、POSIX4相当であれば十分、というのは何を根拠にしてます?
自分が必要だなーと思う基準ですが:
- 周辺ライブラリ(libc含む)がMT-safeかどうかを考慮されたもので構成されているか
- それらがOSからのサポートを受けているものか(ユーザーが作ったwrapperではなく)
- それらの情報が揃っているか
- 実際に役に立つライブラリがあるか(藁
というのを考えると、一番win32、時点SolalisもしくはJava じゃないですかね。
単一ベンダが OS、開発環境、アプリケーション作ってりゃ当たり前なんですけども。
OSオタクでなく、実際にアプリケーションを書いている人の意見を求めます。
31 :
30 :2001/08/10(金) 08:56
"であれば十分" → "であることが必要" ですねスミマセン
32 :
デフォルトの名無しさん :2001/08/10(金) 09:31
>>13 その本面白そうだね。
Javaやる人って必ずGoFやると思うんだけど、
あれやっても構造に関しては一応それらしいものが作れるようになりましたって
なるけど、Javaの利点の一つのクラスにスレッドを簡単に割り当てられる、
これをどう活用したらいいのか?これにはあんまり参考にならないんだよね。
買ってみるかな。評者の★の数が全部満点なのがなんか怪しいがw
33 :
デフォルトの名無しさん :2001/08/10(金) 09:43
>>18 読み込み→インクリメント→書き込みのフェーズになるから、SMPではロックし
ないと他のCPUと競合する可能性がある。NTじゃなきゃ起きないけど。
>>30 > あと、POSIX4相当であれば十分、というのは何を根拠にしてます?
そんな事言ってない。「一番揃っている」のはwin32じゃないと言っただけ。
Solaris 8はPOSIX 4をほとんど実装しているが、win32はそうではない。
>>21 > 一番揃ってるのはwin32っぽいですね。
という文章に対してさ。
それ(一番揃っている)を要件にすると、
> というのを考えると、一番win32、時点SolalisもしくはJava じゃないですかね。
一番Solaris、次点win32、その他、
Javaはplathomeによる(VMの完成度が違うので)、じゃないかな?
(MacOS X, AIX, Tru64などマイナー系は省いた)
> というのを考えると、
って言ってるけど、新しく要件作れば、そりゃどんな順序にでも出来るでしょ。
俺は
>>21 の「一番揃ってる」に対して言ってるんだよ。頼むぜ。わけが分からん。
そもそも発端の
>>11 の"freeの"からも外れていってるしさ。
> スケジューラって具体的に何を指してますか?
スケジューラですけど?
>>30 以外関心ないかも知れないのでsage
>>30 の基準から考えるとマイナーながらBeOSが一番揃ってるね。
>>35 BeOSはあるバージョンアップのときに、大きな変革をやらかしたおかげで
既存アプリが大打撃を食らったそうだ。Mediaなんとかだっけかな。
そういう意味での安定性も必要だと思う。
>>34 POSIX準拠って何か役に立つの?
もしかして、すっげーくだんねえ話してる?
38 :
デフォルトの名無しさん :2001/08/11(土) 01:10
POSIXに準拠したスレッド、バリバリ使ったアプリとかあるの? あるならおせーてくれ!
39 :
デフォルトの名無しさん :2001/08/11(土) 03:09
スレッドと言ったらやっぱりNTでしょ Linuxは、スレッドは実装してないんでは???
POSIXは今後出てくる(であろう)OSに対する設計方針としての 標準インターフェイスを目指してるのかもしれないから、 既存のOSが準拠すべきものではないのかも。 POSIXに準拠していようがしてなかろうが、最終的にはその 実装、性能でしょ。SMPに対するスケジューリングの効率。 沢山プロセッサの乗ったマシンなんて使ったことないから 分からないけどNTのスケジューリング悪くないらしいよ。 聞きかじりの話だからあてにならないけどさ。
41 :
無党派さん :2001/08/11(土) 05:43
42 :
11 :2001/08/11(土) 08:41
43 :
デフォルトの名無しさん :2001/08/11(土) 12:07
44 :
デフォルトの名無しさん :2001/08/11(土) 12:47
話変わっちゃうんだけど、自前でセマフォって作れるの? 俺、頭悪いから良く分からないんだけど、どうなの?
45 :
デフォルトの名無しさん :2001/08/11(土) 14:25
>>44 とりあえず入手が楽なlinuexthreadsかpmpthread(*BSD)のsourceでも眺めてみたら?
linuxthreadsにはsemaphore.cってのがあるよ。
46 :
デフォルトの名無しさん :2001/08/11(土) 14:38
>>43 Javaのthread仕様は、pthread規格策定時の研究が反映されてなかったね。
47 :
デフォルトの名無しさん :2001/08/11(土) 15:14
だれかソース見せてもらえませんか?
50 :
デフォルトの名無しさん :01/08/29 23:03 ID:ufAQmXP2
signal()でSIGALRMを補足して関数を実行させる事を マルチスレッドで行いたいのですが、うまくいきません。 スレッドではなくプロセスが補足してしまうからなのですが これをスレッド毎に行う良い方法は無いでしょうか? できれば参考となるソースが読みたいのですが なかなかありません。
51 :
デフォルトの名無しさん :01/08/30 00:01 ID:C3TsWUik
>>50 OSは?thread libraryは何か分かる?
53 :
50 :01/08/30 08:25 ID:ZcipkBQk
>>51 OSはLinuxで、thread libraryは、POSIX.1c
です。
54 :
デフォルトの名無しさん :01/08/30 14:00 ID:C3TsWUik
>>53 > OSはLinuxで、thread libraryは、POSIX.1cです。
linuxthreadsなのかな?
linuxthreadsは、規約にあってないところがあって、それが
>>50 とも関連していると思います。
詳しくはREADMEをの最後の辺りを読んでください。
>>26 も。
それから、この制限はlinuxthreads自体に由来するのではなく、
clone(2)自体に由来しますから、他のthread libraryを使っても駄目です。
close(2)を使わないuser level threadであるpmpthreadsも芳しくありません。
55 :
IDEなんてクソ :01/08/30 22:01 ID:ZAelFQ6s
pthredとBSD系のシグナルは競合するから同時に使わない方がいい。 ついでに言うと、pthreadでシグナルは極力使わない方がいい。 どうしても使いたいときはシグナル受信スレッドをpthredのシグナル関数群を 使って実装して、他のスレッドはシグナルを受信しないようにマスクする。 このあたりはアスキーから出ている実戦マルチスレッドプログラミングを 熟読するとわかると思うよ。
56 :
デフォルトの名無しさん :01/08/31 01:50 ID:JrJLvbeM
>>55 > ついでに言うと、pthreadでシグナルは極力使わない方がいい。
つーか、かなり注意して使わないと、ってことじゃないかな。
同期し協調して動くthread群に、非同期で割り込んでくるわけだからね。
「どうしても」以下に書いてあるような工夫を応用毎に考えないと。
ダグ何とかさんのJavaのthreadの本もいいよね。高いレベルの設計話としては。
57 :
50 :01/08/31 20:34 ID:rIUxoozo
>>51 >>54 >>55 >>56 返事遅くなりました。
情報どうもです。なるほど〜、やっぱりマルチスレッドでの
シグナルは難しいしバグの温床にもなりやすいので
やらんほうがいいわけですね。私もあの後いろいろ
本を調べてみたのですが、シグナルハンドラ用のスレッド
を別途設けて他スレッドからのシグナルを全てその専用
スレッドで取り扱うようにするのが一般的みたいですね。
この場合不思議なのは、どのスレッドから発せられた
シグナルかを区別しないといけない場合どうやって区別
するのかということです。
58 :
:01/08/31 23:34 ID:K2I6K2jM
シグナルを受け取ったプロセスは、終了するのが基本だったんだけど いつのまにか、プロセス間の通信に使われるようになって おかしなことになってる。
59 :
デフォルトの名無しさん :01/08/31 23:34 ID:JrJLvbeM
>>57 > この場合不思議なのは、どのスレッドから発せられた
> シグナルかを区別しないといけない場合どうやって区別
> するのかということです。
signalはそういう機能(発信元告知)を提供してくれない。
けど、process内部のthreadからのsignalならば、
process内の事は自分で管理できるよね?
いずれにせよ、本当にsignal、つまり非同期的である必要があるのか?
必要があるとすれば、受け手側が割り込まれていいのはいつか?
signalは同時多発的に起きるかどうか?
なんて事を考えないといけないわけだけど、
よくよく考えると最後の部分は「割り込み」でやるんじゃなくて、
同期的にやった方が簡単だよね? (もちろんそれでいい場合は)
lockを保持したまま割り込まれちゃう事なんかを考えると。
pthread_cancelについて調べると、この辺の設計の指針が得られると思うけど。
> 本を調べてみたのですが、シグナルハンドラ用のスレッド
> を別途設けて他スレッドからのシグナルを全てその専用
> スレッドで取り扱うようにするのが一般的みたいですね。
となる理由も良く分かるだろうし。
60 :
これ定説? :01/09/01 00:05 ID:8UdnvL3A
Javaスレッドはクソ
61 :
57 :01/09/01 00:47 ID:YEBV7iy6
>けど、process内部のthreadからのsignalならば、 >process内の事は自分で管理できるよね? ふむ、何となくわかった気もする。 >pthread_cancelについて調べると これ調べてみますです〜。
62 :
IDEなんてクソ :01/09/01 01:11 ID:N2P03Y3g
UNIX歴長い人はすぐにシグナル使うけど、 マルチスレッドを使う場合は、極力シグナルを 使わない。素直にmutexを使った方がいいと思う。 プロセス間で通信する場合は、共有メモリでやれば、 シグナルより柔軟にできる。 それが難しいなら、マルチスレッドではなく古典的な マルチプロセスでやったほうがいいよ。
63 :
デフォルトの名無しさん :01/09/01 01:40 ID:/npc6JZk
>>60 > Javaスレッドはクソ
メモリ管理しないでいいところとか、
VMに囲われていてOSのnative API使えないところとか、
thread programmingのいやらしいところに首突っ込まないですむから楽。
もちょっと過去の研究の成果を踏まえて欲しかった部分もあるけど。
>>60 定説。synchronizeキーワードが特に酷い。
いわゆる普通のthreadでなので、その点においては、
プログラミングの上で特に楽になるということはない。
むしろ中途半端な仕様のせいで混乱する可能性が高い(yieldのタイミング等)。
初心者には勧められない。
利用者に徹するなら問題ないと思うけど、それは他の言語(系)でも同じ。
提供者になるなら、標準パッケージのソースは一度見ておくこと。
嫌になるよ。
65 :
デフォルトの名無しさん :01/09/26 04:32
13の本はとってもいい本だったYO
66 :
デフォルトの名無しさん :01/09/26 12:41
マルチたん・・・
67 :
デフォルトの名無しさん :01/09/26 16:01
>>64 >標準パッケージのソース
っていうのは、java.lang.Thread.javaのことではない?
見てみたら、nativeばっかりで、実体はわからなかった。
>synchronizeキーワードが特に酷い
というあたり、少し具体的に教えてもらえませんか。
>>67 >っていうのは、java.lang.Thread.javaのことではない?
たとえば、PipedInput/OutputStreamとか。
synchronizedについては...
1: protectedなメソッドが継承クラスでsynchronizedになっちゃった。
という状況で何が起こるか考えてみよう。
2: synchronizedで待ってるスレッドを中断させることができるか
できないか、について考えてみよう。
69 :
デフォルトの名無しさん :01/10/08 22:24
Σ(゜д゜lll)ガーン 沈み掛けてる
70 :
デフォルトの名無しさん :01/10/08 22:42
>1: protectedなメソッドが継承クラスでsynchronizedになっちゃった。 >という状況で何が起こるか考えてみよう。 クラスを使うがわの認識不足でバグがでる可能性がある >2: synchronizedで待ってるスレッドを中断させることができるか >できないか、について考えてみよう。 プログラミングテクニックが必要だけど、できる
71 :
デフォルトの名無しさん :01/10/08 22:44
ファイルロック使うんだと。 ださすぎ。
72 :
デフォルトの名無しさん :01/10/08 23:23
>>70 synchronizedでlockを得られないで待っているスレッドを中断させる
のは一般には、できないことになってるけど、どうやるの?
javaさぱーりだけど興味有り監視中
74 :
デフォルトの名無しさん :01/10/10 09:54
wait/notifyを使ってsynchronizedと同等の動作を作り込んでやれば、待っているThreadの中断も可能。 っていみじゃないかな。
synchronizedで待っている、というのは大前提じゃないのか。 とりあえず、sage
76 :
デフォルトの名無しさん :01/10/10 10:14
>>74 wait/notifyは、そのオブジェクトのロックを持っているスレッドから
しか呼び出せない。つまり、synchronizedメソッド(ブロック)の中で
呼び出す必要がある。
synchronized ブロックの中で wait すればモニタ手放すんじゃ? 茶々気味だが...
つーか、wait/notify と Thread#interrupt() か。
>>74 > wait/notifyを使ってsynchronizedと同等の動作を作り込んでやれば、待っているThreadの中断も可能。
> っていみじゃないかな。
synchronizeキーワードは使うなって結論?
80 :
デフォルトの名無しさん :01/10/10 10:53
元の問題は、 >2: synchronizedで待ってるスレッドを中断させることができるか だろ。 この意味は、synchronizedメソッドまたはブロックに入るために、 ロックの獲得を試みて、得られなく(他のスレッドが持っている)、 待っている、ということだよね。 こんな状況で、どうやってwait/notifyとかできるのよ。
だからモニタ持っているスレッドが wait すればモニタ手放して別の スレッドが synchronized ブロックに入るじゃん。
82 :
デフォルトの名無しさん :01/10/10 17:26
ていうかマルチスレッド難しすぎ。 ここの人達がどれだけマルスレッド使いこなしてるのか疑問。 ていうか難しいと思ってるのは漏れだけかな(自爆
初歩的質問で悪いんだけど、マルチスレッドで気をつけることの、 ・変数を保護しないと、途中で値が(他のスレッドにより)変更される事がある。 っていうのは分かるんだけど、 ・リエントランスを防がなくてはいけない。 ってどういうことなの?
>>83 状況をもっと書いてもらった方がいいと思うけど?
リエントラントを許してもマルチスレッドにする方法はあるけど?
>>82 マルチスレッド自身は別に難しくもなんともないよ。
javaの実装がヘタレなだけ。
86 :
デフォルトの名無しさん :01/10/10 21:04
>1: protectedなメソッドが継承クラスでsynchronizedになっちゃった そもそも設計ミスを言語仕様のせいにしてるところが問題なのでは? >2: synchronizedで待ってるスレッドを中断させることができるか できないけど なんの問題もない これが問題だと思ってるなら、才能が無いと思って プログラマーやめた方がいいと思うよ
他人の設計ミスをかぶらなきゃいけない 締め切り間近の追いつめられたプログラマもいたりして
>これが問題だと思ってるなら、才能が無いと思って >プログラマーやめた方がいいと思うよ こんなことをいうのは802だけだから気にしなくていいよ
やめちまえ!! なんか昔の職人さんみたいw
90 :
デフォルトの名無しさん :01/10/10 22:53
才能が無ければ普通はやめた方がいいと思うが それとも、プログラミングが一番得意だったりして(笑)
じゃあ、802師匠は大学院生にもなって童貞ですけど男をやめたほうがいいのでしょうか? それともオナニーが一番得意だったりして(藁)
92 :
デフォルトの名無しさん :01/10/12 21:19
93 :
デフォルトの名無しさん :01/10/13 16:19
磨・屡・稚・棲・麗・怒!
synchronized にしているってことは その処理をしている間は他から一切いじられては困るはず stopで強制終了させてしまうと触られてはまずい状態のまま 同期は解除されてしまう とゆう単純なはなしですよね。 分かっててやるぶんには問題ないのだろうけど ほとんどアプリの強制終了くらいにしか おいらはうまい用途が思い付かない。 そんならexit()でいいじゃんってことに、、、 ところで自分はJavaのスレッドくらいしか知らないんだけど 世の中にはもっとスゴイ便利なしくみやライブラリが ありそうなきがするです。 ※のスレッドはほにゃららで凄いんだぜ とかほげほげで便利だぜ とかいうのを識者にぜひ自慢していただきたい所存
96 :
デフォルトの名無しさん :01/10/13 23:58
>>95 スゴイ便利な仕組みと言えば「セマフォ」
大昔からある同期機構なのに、これさえあれば
Javaのwait/notifyのようなことはもちろん、
mutexもリードライトロックも作れる。
できないのは、タイマーや、Javaで言うyieldみたいな
スレッドのスケジューリングに係わることかな。
それ以上のレベルのことをスレッドライブラリ自体に求める
必要は必ずしもないと思うが。
こういうことは、もっと上位のライブラリか
アプリケーションで実装すればいい。
足りないのは便利なライブラリではなくて、
並行プログラミングをちゃんと理解している人間の方。
余談だけどDBのトランザクションが一番身近で
スゴイ同期機構だと思うぞ。
厨房でも理解できるし。
Adaのランデブーよ、今こそ復活せよ!
98 :
デフォルトの名無しさん :01/10/14 00:44
>>94 >2についてはsynchronizedで待っているスレッドは原則として中断できない。
>(Thread#stopで停止はできるが、これは危険!)
Thread#stopで、lockの獲得を待っているスレッドを停止できる、とは言えないのでは?
例えば、スレッド1がロック1を持ち、スレッド2がロック2を持っていて、
スレッド1がロック2を獲得しようとして、同時にスレッド2がロック1を獲得しようと
する、いわゆるデッドロックの状態で、別のスレッドからスレッド1のstopを呼んでも、
スレッド1は停止(中断)しない。結局、デッドロックは解消しない。
元の問いが、synchronizedで待っているスレッドを中断する、ということだから、これは
stopでもできないというのが正解では?
mutexなどの利用については、その通りだと思うけど。
99 :
デフォルトの名無しさん :01/10/14 05:47
定説1:メインスレッドから複数のスレッドを呼んではいけない。 (Javaに限らず、パターンか何かでありませんでしたっけ?)
>>99 え、そうなの?
ワーカースレッド(代表)経由で呼べって事かい?
>>98 もしかして、デッドロックが起こるような状況でしか
synchronizedで待つことはないと思ってる?
>>101 何かお互いに誤解があるようだね。
漏れは、「synchronizedで待つ」、の意味を、例えば、
synchronized void doSomething(){}
というメソッドをあるスレッドが実行しようとして、thisのロックを他の
スレッドが持っているために、待たされている状況を想定している。
もちろん、ロックを持っているスレッドが、そのロックを手放せば、問題ないけど
そうでない場合に、どうか、ということ。
それ以外に、synchronizedで待つことを、問題にする理由がわからない。
synchronizedがロックの獲得を待つのは、問題、ではなく仕様。ただし、
タイムアウトの手段はない。例え推奨されないstopメソッドでもね。
デッドロックの例をあげたのは、この点を理解しやすいと思ったからだよ。
それを問題として捉えるかどうかだけど、タイムアウトが必要な場合は、
mutexとかで対応すればいい。
逆に、synchronizedの手軽さは、javaのメリット、というのが漏れの判断。
>>99 それはもしかして、
「UIスレッドは出来る限りロックしてはならない」
という類のこと?
Win32なんですけど、 MFC並みのC++用マルチスレッドライブラリって何かありませんか?
mfc並って、つまりなんもやってないどころかよけいな手間が増えるすばらしいライブラリがほしいのか? 素直にWin32 APIかpthreadつかえ。
CreateThreadってなんか継承とかあったりしてやたらめんどくさかった 記憶があり。ヘタレにはちとつらいな。
CreateThreadを直に使うことは普通ないと思う。
ハンドルの継承でないの?
MFC使ったってハンドルの継承の問題はあるぞ!
fork とスレッドは似たようなものだと思っていました age
>>110 C runtimeは一切使わないってことか・・・大変そう
C runtimeは不用意に使わないってだけだよ
浮動小数点も使わないとなるときついなあ
浮動小数点なんて使ったこと無い。 あったとしてもprintfの%出力ぐらいか。
TLSも不具合ありそう。
118 :
名無しさん@Emacs :01/10/27 15:38
pthreadでさあ、read(などのブロッキングするシステムコール)してる 他のスレッドに割り込んでreadをやめさせたいときは、普通どうするの?
119 :
デフォルトの名無しさん :01/10/27 15:50
>>118 なんでread止めさせたいのか判らないです。
readして物理的な待ちに入ったら内部でスレッド切り替えてるけど??
120 :
名無しさん@Emacs :01/10/27 16:04
socketから情報がくることがあるからです。 pipe/select使えばいいのかな? ちと面倒だけど。
pthread_kill( reader_thread, SIGINT ) じゃなくて?
122 :
デフォルトの名無しさん :01/10/27 16:08
>>120 shutdown()しちゃえばいいじゃん
123 :
名無しさん@Emacs :01/10/27 16:25
殺したいわけではないです。 次に移らせたいのです。 pipe/selectでできましたよ。 これでいいのかな?
124 :
名無しさん@Emacs :01/10/27 20:06
pthreadでWaitForMultipleObjects(いずれか)みたいなことって どうやればできるんだろう。わからなくて泣きそう
>>124 無理。だからバカみたいにスレッドを増やすしかなかったりする。
126 :
デフォルトの名無しさん :01/10/28 03:28
>>125 pthreadってたいしたこと無いんだね。
俺が作ったマルチスレッドのアプリで
WaitForMultipleObjects使ってないものはない
127 :
名無しさん@Emacs :01/10/28 09:21
WaitForMultipleObjects(すべて)なら簡単だけどね。
128 :
名無しさん@Emacs :01/10/28 09:57
129 :
デフォルトの名無しさん :01/10/28 10:10
WaitForMultipleObjects(いずれか); って、例えばどういうときに 必要なんですか?
130 :
名無しさん@Emacs :01/10/28 10:24
たとえば、入力ポートがいくつかあって、 どこかにデータが入ってきたら動作を開始するとか。 Win32のsignalオブジェクトに相当するものは 条件変数を使って簡単に作れたから、 WaitForMultipleObjectsに相当するものを汎用的に作るには、 そのsignalオブジェクトを使って スレッド一つにつき一つずつただjoinするだけのスレッドを作って、 joinがすんだらシグナルを立てるようにすればいいのかな。 効率わる〜 もっといい手はないのだろうか。
シグナル用のオブジェクトを Singleton にするんじゃ だめなんか?
OpenMPっていうのはどうなの? これってPthreadと似たようなものなんでしょ? C++で書く事も前提になってるみたいなんだけど・・・
>>124-130 >>131 が正しい。スレッドが個々に Signal オブジェクトを
持つのではなく、単一の Signal オブジェクトに複数のスレッド
から notify を行うようにデザインする。
134 :
デフォルトの名無しさん :01/11/01 09:07
>>133 それだとスレッドがシグナルオブジェクトを知らなければならない。
もっとシンプルに〜
>>134 スレッド開始前にシグナルを渡せば良いじゃん。
Thread t = new AbcThread(signal);
synchronized(signal){
t.start();
signal.wait();
}
てか、どこをどうシンプルにしたいの?
引数渡しすらやりたくないの???
136 :
デフォルトの名無しさん :01/11/01 09:34
スレッドってjavaだけじゃないし
複数スレッドで WaitForMultipleObjects 相当のコード: Object signal = new Object(); Thread[] t = new Thread[10]; synchronized(signal){ for(int i=i; i<t.length; i++){ t[i] = new AbcThread(signal); t[i].start(); } signal.wait(); } public class AbcThread extends Thread{ private Object signal = null; public AbcThread(Object signal){ this.signal = signal; return; } public void run(){ ... synchronized(signal){ signal.notifyAll(); } return; } }
>>135 言いたいことは分かったが、
WaitForMultipleObjects(OR)みたいな美しさがなくていいなら、
pthread_cond_waitで十分できるので。
WaitForMultipleObjects がシンプルで美しいか? まずそこら辺の美的感覚が違うな...。まぁ趣味的な 相違を深く突っ込む気もないので好きにしてくれ。
140 :
名無しさん@Emacs :01/11/01 11:27
スレッドをWin32イベントとして扱えるのは素直に 美しいと思ったが、何か偏見があるのじゃないか。
141 :
デフォルトの名無しさん :01/11/06 21:14
sleep()をVC++6.0SP5(WinNT4.0SP5)でマルチスレッドで使ってるんです。 あるマシンではsleep(2)とかが正常に動作している (PIOボードに出力させてそれをオシロで見た結果) のに、別のマシンでは、小さな値を渡しても10msec以下になりません。 対処法ありますか?
142 :
デフォルトの名無しさん :01/11/06 21:19
timeBeginPeriod
WaitForMultipleObjectsだとすっきり、かつ、美しく書けるんだが これに相当するもののない環境って意外に多い。というかwin32だけ?
threadが発達してるのはwinだねぇ。 そもそも、マルチスレッドがデフォルトっていう概念は、 winが最初じゃない?
145 :
デフォルトの名無しさん :01/11/07 03:09
>141 sleep()でmsecオーダーの動作を期待することがイタい。
146 :
デフォルトの名無しさん :01/11/09 01:26
スレッドを1msec未満の時間スリープさせるなんてことは できるのでしょうか? WinNT+VC++で
147 :
デフォルトの名無しさん :01/11/09 01:49
>>146 割り込みをマスクしてタイマーを監視してればいいだろうが、
システム全体がパフォーマンスダウンして不安定になるだろう。
148 :
デフォルトの名無しさん :01/11/09 01:51
NTで割り込みをマスクするってデバイスドライバでもムリかも。
何をやりたいのか書けば?
>>146
いわゆるunixだとthreadは完全に後付けだね。 machが研究的にあれこれやってたみたいだけど、 実用OS上でインプリし、かつ実用しているのはwin32が最初かも。
150 :
デフォルトの名無しさん :01/11/09 01:57
そもそも一ミリ秒以下の間隔でデータの受信が 複数のデバイスで発生したときに、アプリが 割り込ませてくれなければ、ちゃんとシステムは動かない。 どうしてもやりたきゃネットワークもハードディスクも ないワンボードマイコンでやるしかないだろうと思われ。
151 :
デフォルトの名無しさん :01/11/09 09:14
RS232Cで送受信できるプログラム作ってます "123456789"のcharデータを送信するプログラムと それをスレッドで受信するプログラムを使い、テストしました 結果は 123456789 12543789 123456 などスペースが勝手に入ったり、改行したりしなかったり 順番が入れ替わったりしました 正確な受信をすることはできるのでしょうか? お願いします
言葉足らずですみません。 【目的】 あるスレッドでパルスモータをPIOボードを通じて回したい。 【課題】 PIOボードへの出力後、スリープさせたいが、 1msec単位でしかスリープできないと、回転速度をきめ細かく設定できない。
153 :
デフォルトの名無しさん :01/11/09 12:26
forkとスレッドって代替するものなの? forkはもういらないって事?
154 :
デフォルトの名無しさん :01/11/09 12:53
>>153 んなこたぁない
forkの方が便利な場合も依然としてある
155 :
デフォルトの名無しさん :01/11/09 13:11
>>151 まずはスレッドを使わないでちゃんと受信ができているかテスト。
>>152 どう考えてもマルチスレッドの質問じゃないと思われ。
>>153 モジュール間の結合度が低くてデータのやりとりがIPCで十分な場合、
forkを使う方がいいと思ってる。
メモリ空間を共有するならスレッド。
159 :
デフォルトの名無しさん :01/11/09 23:33
>>152 分かってないなあ。
正確さをあきらめるならタイトループを
ベンチマーク的に測定してテキトーに。
たぶんきれいな方形波でなく、
不揃いのパルスになる。
正しくパルスを送るんなら、そのデジタルI/Oボードに
そのパルスを発生させるICを何とかして繋ぐのが正攻法。
H8なんかはPWMとRS232を内蔵していて便利。
ちょっと古い話ですみません(
>>18 のWin32のロックについて)。
>InterlockedIncrement()はなんでガードしないと行けないんですか?
マルチプロセッサ環境で問題が出ます。
inc命令といってもリード/ライトサイクルがあり、その間に他のCPUが処
理する可能性があります。実際、マルチプロセッサマシンでそんな不具合
が起きそうなプログラムを書いて試してみてください。
非x86のときは、x86の命令に対応するものに展開される保障はありません
(>20も少し触れている)。
>>157 やっぱマルチプロセスもいいよね。プロセスの死亡は痛くないけどスレッドの死は
痛い。あと信頼度の低いものをまとめあげるときには、疎な結合のほうが
いいから、プロセスを防波堤として使うのも好き。
にしてもマルチプロセスのときのプロセス間の連絡って皆どうしてんの?
POSIX IPC? System V IPC? pipe? socket?
それともRPC? またはCORBAとか分散オブジェクト使うの?
>156 言葉足らずでしたか。スマソ ステッピングモータを回すスレッド以外に、通信や表示のスレッドがあって、 モータを回す際にスリープを正確にさせたい。
>>164 みたけどー。
要はmsec未満のスリープはできないのね。
>>152 そこまでの解像度を持つタイマが必要なら
もはやNTの出る幕ではないのでは…?
リアルタイムOSとか必要なんでは? よく知らんけど。
167 :
デフォルトの名無しさん :01/11/13 03:08
[参考]マイクロ秒単位の話: 以前NT用のセントロボードの読み出しドライバーで、 割り込みの奴とストローブをCPUで監視する奴の2種類 付属している奴があった。 その注意書きに、割り込みなしの奴は取りこぼしあり とあり、保証なしだが、全く使えないわけではなく、 テキトーもありなんだとちょっと感心した。
168 :
デフォルトの名無しさん :01/11/13 14:49
マルチメディア系のライブラリなら、 マイクロ秒単位でタイマーの監視は出来そう でも、それをやるとCPUがそれにかかりきりで、 ほかのスレッドを動かせなかったりするんでは。
>>166 だから
>>159 見ろと何度も言われてるのに取り合わない馬鹿は
ほっといて勝手に困らせとけ。
170 :
デフォルトの名無しさん :01/11/13 17:52
171 :
デフォルトの名無しさん :01/11/15 00:51
>169 ただのヴァカ
いにしゃらいずくりちかるせくしょん
複数のスレッドから同じ関数を呼び出しちゃマズイですか? 関数内ではstaticな変数は使っていないんですが、、、
基本的にはなんら問題ない。競合問題というのはデータに対して起きるもので、 コードに対して起きるものではないから。 実は同じオブジェクトを引数に渡してて、そいつが競合してるとか?
ありがとうございます。 大丈夫なんですね。
176 :
名無しさん@XEmacs :01/11/15 12:23
>>173 > 関数内ではstaticな変数は使っていないんですが、、、
MT(multi-thread) safeな関数しか呼び出しちゃ駄目よーん。
例えば、UNIXだとgethostbynameはMT-safeじゃない。
gethostbyname_rがMT-safe版。
>>176 呼び出す周囲をMutexでくるむという手もある
すべての箇所で出来るという保証があればの話だが
178 :
デフォルトの名無しさん :01/11/15 14:27
>>173 別にマズくないです。
同じメモリ領域に、複数のスレッドで同時に書き込んだり、
あるスレッドから書き込むと同時に別スレッドで読み込んだり、
しない限り全然大丈夫です。
「同時に同じ領域へアクセスしなければ特に排他処理をしなくても問題ない」 と理解しましたが、それでOKですか?
180 :
デフォルトの名無しさん :01/11/15 16:55
>>176 たまに表示が化けたり原因不明のエラーを出すの得意だろ
>>179 同時に読み出しだけならOKです。
書き込みが混じるときは気を付けましょう。
182 :
デフォルトの名無しさん :01/11/16 00:03
183 :
デフォルトの名無しさん :01/11/16 00:17
便乗で質問させてください。 時刻の取得⇒文字列として表示、にlocaltime, ctimeを使おうと思ったのですが スレッド安全ではないために、localtime_r, ctime_rで記述しました。 ところがコンパイルは通るものの、実行すると上記箇所にて coreを吐いて死んでしまいます。 (localtime, ctimeで記述時の動作は、期待通りです) Solaris8, gcc295を使用しているのですが、 "*_r"関数には、何かしらの制限等があるのでしょうか?
取得から表示(もしくは中身のコピー)をするまで、クリティカルセクションで挟んどけ。 mutexでもいいぞ。
萎えるな、それ。
>>183 とりあえず「スレッドセーフ」って読んだほうが良いかと...。
>>179 どういう構造でmulti-threadが実装されているのか理解するまでは
愚直に危うそうな資源を排他するのをおすすめします。
「同時に同じ領域へアクセスしなければ特に排他処理をしなくても問題ない」
という表現に危うさを感じます。
たとえば、排他をしないでどうやって同時でないことを保証しましょう?
188 :
名無しさん@XEmacs :01/11/16 03:31
>>179 マルチスレッドセーフって概念も理解したかどうか不安。
>>180 何でしょ?なにか用ですか?
189 :
デフォルトの名無しさん :01/11/16 03:38
localtimeもctimeもスレッドセーフだと思うのは俺の気のせいか?
*_rは、結果文字列バッファを引数で渡すので、ちゃんと確保してればスレセーフ。 フツーのlocaltimeとかctimeとかは、ライブラリ内部の?共通バッファに 結果を展開するので、別のスレで使われると、書き換えられる可能性がある。 ということじゃなかったかな? まあ、あんまりセーフかどうかを気にしなくてもいいのかもしれんが、建前上はスレセーフではない。
VCだと*_rがないけど、マルチスレッドライブラリのリンクで 保障されるのかな
皆様のご指摘どおり、メモリを確保していないために 起きた現象でした。 メモリ確保をすることによって無事解決をしました。 ありがとうございます。 メモリを確保する必要があるのですね、知りませんでした。 その必要性は、以下のような解釈でよろしいですよね。。。 localtimeは、関数内static領域を保持することを前提に設計された関数であり localtime_rは代替関数である。この関数はライブラリ内部の共通バッファを 使用しないことによってスレッドセーフを実現しているため、当然 自前でメモリを確保する必要性がある。
>>191 VC++の場合、マルチスレッド用のランタイムは内部で
動的なバッファを確保してる。
194 :
デフォルトの名無しさん :01/11/16 13:18
VCはランタイムライブラリの持つグローバル変数は全部TLS(スレッドローカル領域)
なので、大丈夫だよ。
>>191
全部じゃないだろ。そんなことしたら排他制御もできん。
排他制御はOSの機能でやってるんでしょ ま、「全部」ではないと思うが
197 :
デフォルトの名無しさん :01/11/16 16:40
質問よろしいでしょうか? 常駐処理をスレッドで作成しています。 スレッドが終わった場合に、もう一度起動するように しようとしているのですが、 終わった筈のスレッドなのにGetExitCodeThreadでのコードが STILL_ACTIVEになってしまいます。 何かおかしいでしょうか?コードは次のようなものです。 よろしくお願いします。 void main() { 〜略〜 while(1) GetExitCodeThread( (HANDLE)hThread, &ExitCode ); if( ExitCode != STILL_ACTIVE ){ hThread=_beginthread( ThreadProc, 0, (VOID *)NULL); } } } void ThreadProc( void *p ) { /*処理*/ return; }
198 :
デフォルトの名無しさん :01/11/16 16:46
mainもThreadProcも戻り値必須だボケ
200 :
デフォルトの名無しさん :01/11/16 21:07
てか、ちゃんとスレッドプロシージャの型を見ような。 cdeclとstdcallとではスタックの解放の仕方が違うんだよ。 大方、リターン直後でスタック破壊を起こしていると思われ。
>>192 =183
ちょっと話題がずれるけど、ポインターをやりとりする時に
実態の領域を誰が用意するかはドキュメントを読まないと
判らないのはC言語の限界ですよね。。。
用意するにしても、領域の大きさも表現できないし。
>localtime_rは代替関数である。
代替かなぁ?
localtimeの仕様が気に入らない人が多くって、
thread-safeにするついでに関数の定義を直しちゃったとか?
>>201 sprintf→snprintfという変化もあるよ
thread-safeとはまた別に。
203 :
名無しさん@XEmacs :01/11/18 02:45
>>201 > thread-safeにするついでに関数の定義を直しちゃったとか?
1. 仕様を変えないとMT-safeにならない。
2. 勝手にmallocするようにしないとMT-safeにならない。
という究極の選択で、1を選んだという事。
Lisp, Java, C#が2を選んで、
> 実態の領域を誰が用意するかはドキュメントを読まないと
> 判らないのはC言語の限界ですよね。。。
を克服するためにGCを採用した(知る必要なし)のはご存知の通り。
204 :
デフォルトの名無しさん :01/11/18 06:07
>>194-196 thread safeじゃない物はstruct _tiddataでまとめてTLS管理してる
ようだが。crt/src/mtdll.h辺り参照。
205 :
デフォルトの名無しさん :01/11/19 20:06
Windows&VC++環境で親スレッドから子スレッドを終了したいのですが、 どうしたらいいので良いでしょうか? 自分で調べた中では、自分自身(呼び出し元)を終了させる方法しか 見つかりませんでした。
誰かが(親でも子でも、別EXEでも)社内掲示板(同期オブジェクト)を使って、リストラの通知をする ↓ 仕事しながらたまに社内掲示板を待ち時間ゼロとかで調べる ↓ 終了通知が来てたら、仕事を辞めて首をつる ↓ スレッドハンドルとかを待機して解雇を確認する スレッドハンドルで解雇の確認ができないときは、死に際に 遺書(同期オブジェクト)を残す ↓ 解雇完了
TerminateThread
だせーよおまえ
209 :
デフォルトの名無しさん :01/11/20 00:56
>>207 どうもです。
TerminateThreadについては、参考書に例として載っていましたが、
リスキーなので使わない方が良いと書かれていました。
他に安全な方法は無いでしょうか?
211 :
デフォルトの名無しさん :01/11/20 01:03
>>209 206の解説:子供スレッドはある変数を監視し、それがある値に
なったら終了するようにしておく。親スレッドは、終了させたく
なったら、その変数をセットする。
当然だけど、子供スレッドは定期的にその変数を監視しないといけない。
かなり面倒。通信量が少ないなら別プロセスのほうが楽かもね。
任意のタイミングで無理矢理殺せるスレッドライブラリは少数派。
つかSolaris以外に知らない。
>>211 >任意のタイミングで無理矢理殺せるスレッドライブラリは少数派。
ただのpthreadでは...。(普通のUNIXで採用しているthreadね(かなり略))
単純に終了のための変数参照でもいいし メッセージループと同様の作りでもいい、こっちの方がメッセージ 遅れるので融通利く
みなさんinet_ntoa()ってどうしてます? 私は代替にスレッドセーフなやつを適当に 自作してつかっちゃってるんだけど・・
俺はinet_ntop()を使うようにしてる。ついでにv6対応にして(゚д゚)ウマー。
216 :
デフォルトの名無しさん :01/11/20 09:49
通信デバイスにアクセスすると、たまに「ERROR_OPERATION_ABORTED」という エラーが返ってくるんですが、これってどんなことが起こってて、どう解決していけば いいのでしょうか? VC++なんか初めてなのにマルチスレッドのプログラムのデバッグやらなきゃ いけなくてヘルプ見てももうさっぱりです。 他のスレッドが使っているのだろうか?などとも考えたのですがそれをどうやって 調べればいいのかもわからないです・・・ ホントどうしようもなくシロートで申し訳ないんですが、よろしくお願いします。
>>214 WindowsNT以降ではinet_ntoaはスレッドセーフ(同じスレッドで再度Winsock関数が呼び出されるまで返された文字列は有効)だ。strtokも同様。
218 :
デフォルトの名無しさん :01/11/20 23:36
219 :
デフォルトの名無しさん :01/11/20 23:37
普通のunixで採用しているthreadって何?
220 :
デフォルトの名無しさん :01/11/21 00:20
>>211 解説どうもです。
>>213 やっぱり、皆さんの提案されるような小技をつかわないと実現できない
のでしょうか?
シンプルに命令一つで実現できないものかと調べています。
あっても良さそうな命令なんですが、やっぱ別スレッドを終了させると
言う事はあまり良くない事(いろいろと問題がある)なのでしょうか?
仕様上、今の所は別プロセスを作る事は考えていません。
221 :
名無しさん@XEmacs :01/11/21 00:50
>>220 > シンプルに命令一つで実現できないものかと調べています。
何作ってるか書かないと、
そのthreadが取得しているlockはどうするんだ?
とかいうアドバイスをしにくいぞ。
222 :
デフォルトの名無しさん :01/11/21 00:55
スタック以外何も占有していなければ、外部からTerminateしても問題なし。 そのスレッド内で使用するあらゆるリソースのためのマネージャを、メインスレッドが管理すればいい。 ただし、トランザクション中だけ、メインスレッドが待機する仕組みを必要とする。 で、そういうプログラムを以前1回仕事で作ってみたけど、問題なく動いてはいるね。 (子スレッドが使用するリソースがある程度限定できたからだけど。)
223 :
デフォルトの名無しさん :01/11/21 01:18
>>220 理解しやすいように具体例を挙げると、こういうことです。
次のようなスレッドがあるとします。
void thread()
{
FILE* fp = fopen("a.txt", "r");
/*ここで色々な処理をする*/
fclose(fp);
}
メインスレッドからこのスレッドを終了させようとする場合、
このスレッドは、まだ処理実行の途中ですよね?
スレッドを途中で終了させたら、fclose は実行されないですよね?
困りませんか?
ここでfcloseが確実に実行されるためには、
(1) メインスレッドで fclose を実行する
(2) 子スレッドが自分で終了処理して fclose を実行する
のいずれかですが、FILE* fp がローカル変数だったら、
メインスレッドからファイルを閉じる方法は実行不可能です。
メインスレッドから子スレッド終了させると、
子スレッドは fclose を呼ぶヒマなく終了させられますからダメです。
そーすると、終了フラグを立てるなりして
子スレッドが自主的に終了するよう仕向けるしかないわけです。
おわかり?
>>222 但し書きのないいつ殺してもいいスレッドなんて
業務プログラムでは皆無だな(藁
ゲーム系ならあるのか?
>>220 残念ながら命令ひとつてポンってのはないよ。
スレッド管理をしてくれる魔法のつえなんてどこにもない。
ほとんどの場合同期処理が絡んでくるから、
設計は慎重に、コーディングは明快かつ丁寧にやるように。
>>218 >そのpthreadはニセモノだね。
(単語の認識に違いがあるかもしれませんが、)
pthread_kill()は意図した動作と違うのでしょうか?
pthread_kill() send a signal to a thread SYNOPSIS #include <pthread.h> int pthread_kill(pthread_t thread, int sig); DESCRIPTION The pthread_kill() function is used to request that a signal be delivered to the specified thread. As with kill(), if sig is zero, error checking is performed but no signal is actually sent.
>>227 マニュアルは私も引けるのですが、意図はいかがなものでしょう?
「任意のタイミングで無理矢理殺せるスレッドライブラリ」は
ニセモノ?ホンモノ?
227をどう読むと「無理矢理殺す」になるの?
>>228 pthread_killを使えばシグナルを遅れるが、
受け取り側のスレッドが正しくシグナルを処理できないと、
後で悲惨な目に遭うよ。
>>229 (=227?,=218??違うかな?)
UNIXではSIGKILLを送ればシグナルのハンドルできずに終了です。
212がニセモノというオチだったのか
あう? 言われていることの意味がわからんです。 そろそろ眠いけど、教えてほしいです。
元質問者はWinのはずなのになぜpthreadの話になってる?
235 :
デフォルトの名無しさん :01/11/21 11:59
>>221-225 どうもありがとうございます。
> 何作ってるか書かないと、そのthreadが取得しているlockはどうするんだ?
> とかいうアドバイスをしにくいぞ。
はい、其の通りですね。情報が少なくてすみませんでした。
1つのプロセスがあり、親スレッドと子スレッドが常駐しています。
子スレッドでは通信処理(無限ループ処理で、イベント待機していて
イベントが発生すれば通信を行う)を行っています。
今、考えている流れは、
1)メインプロセスから、このプロセスに終了の依頼(アプリ終了処理依頼)
↓
2)親スレッドが子スレッドに終了依頼をかける
↓
3)子スレッド内の処理で通信中であっても通信を強制的に終わらせて
子スレッドを正常に終了させる。(ローカル変数もろもろを全て開放)
※但し、通信中の内容については保証しなくても良い。
↓
4)親スレッドから子スレッドが正常に終了したのを確認した上で、親スレッドを終了。
要は、子スレッドにおいて通信処理を行っている最中に割り込みをかけて
子スレッドを終了したいと考えています。
<現在>
子スレッド(無限ループ)
・イベント待機
・・イベント発生⇒通信処理
<変更>
子スレッド(無限ループ)
・終了依頼チェック
・・終了依頼あり⇒子スレッド終了
・イベント待機
・・イベント発生⇒通信処理
上記のようにも考えてみたのですが、これだと終了依頼をかけても通信中の場合だと
通信が完了して、ループが先頭に戻ってくるまで終了できません。通信中であっても
すぐに子スレッドを終了させたいと考えています。(通信内容については保証しなくて
もいい)
以上、よろしくお願いします。
なんと言うかスレッドの問題じゃなくて非同期通信にしろってだけじゃないのか?
親スレッドで通信のイベント感知して、 スリープしておいた子スレッドを起こした方がよくない?
Windowsはよくしらんけど、もしpthreadなら上にでてるpthread_killでいいじゃん。 SIGALRMを送って、子スレッドの関数がEINTRで返ったのをみて 終了すればいいような…
>>235 窓だったら子スレッドをMsgWaitForMultipleObjects使わせて待機させ、
親スレッドは子スレッドにメッセージを投げることで終了依頼とする
通信を完全に非同期で行なえばメッセージを待つだけでも出来る
UNIXだったらパイプをポーリングすれば親の終了依頼とクライアントとの
通信を同時に待機できる
細かい使い方は自分で調べろ
>>239 >>235 は強制的に終らせてなどと言ってるので通信は
ブロッキングでしたいのだと思われ。
241 :
デフォルトの名無しさん :01/11/21 14:51
242 :
デフォルトの名無しさん :01/11/21 14:59
他のスレッドに例外を発生させる方法って、あったっけ。
Javaなら。 スレッドを外から強制終了させよーとすると ThreadDeath 例外が走る。
244 :
デフォルトの名無しさん :01/11/21 15:15
すまん、舌足らずです。 Win32&C++で、あるスレッドから別のスレッドに例外出せたら、 ちょっと悦なんですが。 ざっと調べた範囲ではなさそうだったんだけど、 見落としてるかもしれんので。 なんか情報あったらください。
Sub Macro1() Dim i As Double Dim iAnswer As Double X = Worksheets(1).Cells(13, 2) A = Worksheets(1).Cells(11, 7) For i = X To A Step 0.0000001 iAnswer = i Next sAnswer = Str(iAnswer) Worksheets(1).Cells(13, 8) = sAnswer End Sub ----------------------------------------- X=C10 A=IF(A13="",""ROUND(B13+E13+F13,6)) と、それぞれのセルには数式が入っています。 Aのセルは sAnswerのセル(13, 8) に数値が入らないとAの答えが出ないから 「#DIV/0!」となってます この状態で実行すると For i = X To A Step 0.0000001 のとこで「型が一致しません」とエラーなります。 「#DIV/0!」だとダメなんでしょうか?
たとえば、そのほかのスレッドで頻繁にアクセスされるインスタンスなどを ゼロクリアしてしまえば、そのスレッドがそのポインタをさわった瞬間に Access Violation例外が発生するようにできますが。 やはりメッセージを受け取って、例外を送出するという方が無難でありましょうか。
>>243 イキナリThreadDeathのはなしより、普通は
「WAITスレッドにInterruptかけてInterruptedException」
のはなしが先でしょうに。
>>242 共有メモリのフラグを時々見に行って、フラグが
落ちていたら例外投げればいいじゃん。
249 :
名無しさん@XEmacs :01/11/21 18:40
>>244 > ざっと調べた範囲ではなさそうだったんだけど、
> 見落としてるかもしれんので。
「Win32 マルチスレッド プログラミング」J. Beveridge, R. Wienerでは、
第五章「スレッドを制御する」に「何時間にもわたる調査の結果、
私は確信を持ってWin32 APIは別のスレッドに対して例外を送出するための
標準的な手段はサポートされてないと断言する事が出来る」だってさ。
// ここで言う「非標準の」はdebug APIで
>>246 など。
Compilerはかなり大変だよ、非同期に例外送出されると。
どの命令間でも例外が発生すると思って"exception safe"を維持するなんてさ。
けど、欲しい機能だけどね。pthreadのcancel pointみたいに限定局面でいいから。
250 :
242=244 :01/11/21 23:47
むー、やはりそうか。情報ありがとうございます。>みなさま
251 :
デフォルトの名無しさん :01/11/21 23:50
マルチスレッドとsignalって共存可能かにゃ?
252 :
デフォルトの名無しさん :01/11/26 01:24
あと、何らかの手段で、そのスレッドのeipをとってきて、 スレッドが切り替わらないうちに、throw xxx;相当のコードに 書き換えてしまう、という手段がひょっとするとあるかもしれませんな。 まぁ、マルチプロセッサシステムでどうなるかは知りませんが。
254 :
デフォルトの名無しさん :01/11/26 12:35
排他制御ってどういう時に必要なのでしょうか? 銀行の預金の例、以外には無いのでしょうか?
銀行の預金の例ってなによ?
>>249 QueueUserAPC使えば近いこと出来そうな気がする
あくまで気がする程度だけど……無理かな?
257 :
デフォルトの名無しさん :01/11/26 13:38
>>254 複数のスレッドから1つの変数、ファイル、その他の資源を
アトミックな1つの操作(≒間に割り込みが入らない機械語1命令など)
ではすまない書き込み、あるいは更新
を行う必要がある個所ではすべて必要です。
258 :
デフォルトの名無しさん :01/11/26 15:55
>>254 自販機のボタンを同時押しされたときに
押した分だけ缶コーヒーが出てくる仕組みにしたくないときに
排他制御しろ。
まもなくアホでも理解出るようにと思って書かれたスレッドプログラミングの 本がでます。ご期待ください。 買ってくださったら感謝します。
>>258 ボタンの数だけスレッド(タスク?)が動いているのか!
スゴイ設計だな
>>260 あほが作ったマルチスレッドのプログラムって怖いな(w
263 :
デフォルトの名無しさん :01/11/26 18:09
>>261 オブジェクト指向を始めて学んだときは
そういう設計をして楽しんだよ。
すぐに止めたけど
自販機のボタンを適当に置き換えて読め。 ビデオ鑑賞専用の個室とか、 トイレとか、 なんでもいいぞ。
>>265 すみません。慌てて書き込みました。
たしかにあほが作ったマルチスレッドプログラムは怖いですね。
時間ができたら、あほのためのマルチスレッドプログラミングの
ためのパターンランゲージを書いてみたいと思います。
良いアイデアがでました。感謝します。
267 :
DPの名無し :01/11/28 00:45
あほあほって云わんといてください。 本は買うと思うけど、あほが多数で実装しても困らない設計の進め方を 開発手法の観点から誰かと共著(don't treat)で、web公開してください。 (これぞ救済 あほじゃないやい。あほじゃないやい。DQNなんです。
そろそろ書籍名と出版社を明かしても良いのでは?
>>249 別スレッドの話はともかく、VC だと /EHa で非同期例外処理モデルになるね。
アホほどスレッドを使いたがるから困る ちゃんと教育してほしい
効果的なとこに使えばよい。 なんだってそうだろ?
272 :
デフォルトの名無しさん :01/11/28 02:28
人のことあほあほいうやつはばか
>>270 ここで言っても仕方ない。それは「アホ」なヤツの上司に言え。
274 :
デフォルトの名無しさん :01/11/28 02:39
275 :
デフォルトの名無しさん :01/11/28 11:02
TerminateThread()を実行した後にCloseHandle()でTerminateさせてハンドルを クローズする必要は無いのでしょうか? CloseHandle()で例外が出るのですが・・・
クローズしなくちゃだめです
277 :
デフォルトの名無しさん :01/11/28 14:02
>>275 例外が発生するのはおまえのプログラムが間違ってるからだ。
CloseHandleはしとけ。
TerminateThreadのヘルプはしっかり読んだか?
278 :
名無しさん@Emacs :01/11/28 15:30
なんでそんなにけんか腰なんだ
教育したい相手が先輩だったりするんですが
部分的に貼り付けても、分からないのがマルチスレッドの怖いところなんですけどもね。 グチになってますので去りますすみませんsage
要は「おれはマルチスレッドのテクニシャン」だということかね?
正直、posix threadは本でしか読んでない。 実務ではwin32上でしかマルチスレッドアプリ作ったことない。 でも(゚д゚)ウマー
すいません、windowsで以下のような事できるんでしょうか。 スレッドを作って、そのスレッドの中で、オブジェクトを作って そのハンドルをグローバルにセットして、親からそのハンドルで メソッドを呼び出す事ってできるんでしょうか。
できるがそのハンドルって何なんだよ。 メソッドって何なんだよ。 所有権の管理と同期はきちっとやれよ。
>>285 おそらく、GDCやなんやのグラフィックオブジェクト
ハンドルのことではないか?
依然意味不明だが。
287 :
デフォルトの名無しさん :01/11/30 13:02
235です。 返事遅くなりましたが、>236-240さん、ありがとうです。 まだ自分の中では解決案は出ていませんが、今までの情報を元に がんばってみたいと思います。
電器機の営業をしてます。エクセルとかアクセスとか使って、顧客名と商品購入年月日を入力しておけば、 商品の買い替え時期(買った日からちょうど4年後)に、自動的に表示されるようなプログラム組むことって、できますか? エクセルを少し習っただけの初心者なもので。。
>>288 それはマルチスレッドと、どのような関係がありますか?
>>288 大袈裟なソフト作らなくても
時々4年前の日付で検索かければいいだけじゃないの?
でスタートアップにショートカット入れとけば?
>>285 サーバーを作ってるんですが、とりあえず以下の様な事
ができないかなと思ってます。
初心者なもので、ほんとに出来るのかどうか、かなり
不安な状態です。
1.サーバーとクライアントのクラスを作っておく。
2.親がサーバーのインスタンスを作り、accept処理するメンバ関数を
外部関数を通してスレッド呼び出しする。
3.クライアントからの要求があったら、accept処理するメンバ関数は
クライアントの処理をするスレッドを呼び出す。
その中でクライアントのインスタンスを作り(ハンドルをグローバル
にセット)、recv処理をするメンバ関数でWhileで回る。
4.sendする場合は、親がセットされたハンドルを通して、クライアント
のsend処理のメンバ関数を呼び出す。
親から、
>>292 俺も今、チャットサーバ作ってるんで、知恵を出し合おう。
ていうかほぼ完成してるがね。
>>292 悪いことは言わない、スレッド使うのはやめたほうがいい。
>>294 ま、それは目的によるわな。何百件のクライアントを処理しなけりゃ
ならんようなサーバーではスレッドはキツイが、内輪で使うような
せいぜいクライアント数人のチャットサーバならスレッドでOK。
たしかに学習目的ならまったくもってOKというか好例だね。
298 :
デフォルトの名無しさん :01/12/01 13:43
Linux 上でマルチスレッドを使ったプログラムを作ることになったのですが、 参考図書あるいは URL でおすすめがあったら教えてください。 英語のものでもかまいません。
300 :
デフォルトの名無しさん :01/12/01 13:55
>>298 これなんかどうでしょう?
自分がこれから買うつもりなだけなんだけども(w
>POSIXスレッドプログラミング アスキーアジソンウェスレイシリーズ
>―Ascii Addison Wesley programming series
>David R.Butenhof (著), 油井 尊 (翻訳), 宗方 あゆむ (翻訳)
303 :
デフォルトの名無しさん :01/12/01 15:43
趣味だと動作不良起こしても良いと言う意味だろうか??「
スレッドをオブジェクト化しようとしてスレッド関数を メンバ関数にしようとしてもスタティックじゃないと、 できない。しかし抜け道が。
オブジェクトじゃないじゃん。
306 :
デフォルトの名無しさん :01/12/01 16:11
本買うようなことか?
>> 302
仕事です。(ちなみに、私は 292 ではありません)
以前、Windows2000上で
>>292 と同じような処理をするプログラムを
作ったことがあったので。
>>259 9xだと非常にやばい。
NTだとクリティカルなコードはみんなカーネルモードにあるので
おおむね問題ないけど。
310 :
デフォルトの名無しさん :01/12/16 14:35
Winな話です。 メインスレッド+ワーカースレッド複数個のときに、 それぞれのワーカースレッドからメインスレッドへ SendMessageして特定の処理をしたいのですが、 あるワーカースレッドのSendMessageによって メインスレッドのコールバック関数内に入っている ときに、別のワーカースレッドがSendMessageを 送ってきたとすると、コールバック関数内の コードが並行して走ることになるのでしょうか。 つまり、SendMessageに応答するコールバック関数内の コードで、グローバル変数などの排他制御が必要なのか ということです。
312 :
デフォルトの名無しさん :02/01/17 22:10
Pthreadの説明したサイト誰か教えれ
315 :
デフォルトの名無しさん :02/02/05 23:24
あるスレッドが持つバッファに処理が終了して書いたデータを別の共有バッファにコピーし その共有バッファが見えているもう一つのスレッドに、Notification を送りたいのですが、 (その猛一つのスレッドはそのNotificationを受けるまで待っていて、受けたらそのデータ を処理します。) 普通どう実装するものでしょうか? スマートな方法とかありますか?
317 :
デフォルトの名無しさん :02/02/07 16:17
下のようなプログラムをVC++6.0で書いていますが、 スレッド数が10ぐらいなら正常に終わるのですが、 スレッドを100とか1000にすると、なかなか終わりません。 原因は何でしょうか? #define THREAD_MAX 10 volatile int stop[THREAD_MAX]; void thread_start(void *i) { while(1) if ( stop[(int)i] == 1 ) break; } void test_thread(void) { int i; for (i=0;i<THREAD_MAX;i++) { _beginthread( thread_start, 0, (void *)i ); } for (i=0;i<THREAD_MAX;i++) stop[i] = 1; }
while(1)×1000 が CPU 食いまくっているので for(...) stop[i]=1; の処理が回りにくいから。 ついでに 10 くらいだと thread_start が始まる前に その stop フラグが立ってしまう可能性アリ。 #うそかもしれん。
>>318 ありがとうございます。
100個の時は100分の1のタイミングで切り替わるのではなく
重たいループに優先的にCPUが使われてしまう、と考えていいのでしょうか?
下のようにSleepを入れたら、スレッドが2つでも 終了しなくなりました。 マルチスレッドは難しい・・・。 for (i=0;i<THREAD_MAX;i++) { Sleep(1000); stop[i] = 1; }
あー、なぜイベントを待たないのかね?
スレッドのwhileループの中に Sleep(0) でも入れてみ。
>>320 ビジーループを使う理由は?
マルチスレッドの前にコンピュータの基礎を勉強してみれば?
Win32でスレッド使っうならAdvanced Windowsくらい読んだ方がいい。
専門書って高いよな…… これではずれだった日にはもう……
またブチキレですよ。
327 :
デフォルトの名無しさん :02/02/12 19:55
POSIXスレッドをLinuxで勉強はじめたものなのですが、階層的な構造体のある一部分 だけMUTEXでロックしたいのですが、その場合、pthread_mutex_t 変数を宣言する場所 は、例えば struct B の部分にのみロックをかけたい場合、以下のような風にすれば よろしいのでしょうか? struct A { int a; int b; struct B bb: } stA: struct B { pthread_mutex_t hoge: int c; int d; } stB: struct stA aa;
え?
329 :
デフォルトの名無しさん :02/02/12 19:59
327 スマソ、宣言が何か変でした、もいっかい… struct stB { pthread_mutex_t mutex: int c: int d: } struct stA{ int a: int b: struct stB bb: } struct stA aa:
>329 そのレベルなら好きにすれば?(´ー`)y-~~
331 :
名無しさん@XEmacs :02/02/12 23:45
>>327 ロック変数は、ロックする対象と一対一に対応させて利用しさえすれば、
対象となる構造体の一部である必要はない。
struct T a;
pthread_mutex_t lock_for_a;
でもよい。
>>317 ,
>>319-320 どうしてそうなるかは、Windowsの仕様ではなく、
Windowsの実装や動作環境に依存する話だから、
そんな物に依存しない様に同期を取りながらプログラムを記述せねばならない。
> 重たいループに優先的にCPUが使われてしまう、と考えていいのでしょうか?
そういうことはない。Busy loopがCPUを占有するだけ。
332 :
デフォルトの名無しさん :02/02/13 00:28
327
>>331 ご返答ありがとうございます。なるほど、ロック対象の対応をきちんとすれば
ロック変数の宣言はどこでもいいんですね。しかし一つ疑問が生じます。
pthread側はどこでロック対象のスコープ範囲を知る事ができるんでしょうか?
2つのスレッドAとBがあったとき、AがロックしたリソースをBは解放されるまで
アクセスできないとしたときに、Aがロックするものというのは何でもよいわけですよね?
構造体のインスタンスでも、一つの変数でも、構造体のリンクリストのずっと先の方でも…
ロックされる範囲をBはどのようにわかるのでしょう?
それとも単にAがソースコード中でロックとアンロックをした範囲内のデータは全て
ロックがかかるという事でしょうか?(つまりソースコード依存)
その間に構造体メンバーやグローバル変数が出てきたらそれらは全てロックがかかる
のでしょうか?
∧_∧ < `ш´>.。oO(C言語のスコープは関係しない) pthread_mutex_lockにて明示的にロックし、 pthread_mutex_unlockにて明示的にアンロックする。 保護がかかるのはあくまで*コード*であり、直接データが保護されるのではない。 データにアクセスするコードをmutexで保護することによって、 データへのアクセスがアトミックであることを保証することができるのだ。
331様、333様、どうもありがとうございました。
>>333 どうも勘違いして mutex lock を理解していたようです。これで疑問が氷解しました。
ありがとうございました。m(__)m
336 :
デフォルトの名無しさん :02/02/21 14:04
複数のスレッドのデバッグ情報を1つの画面に吐き出したいのですが、 「Win32マルチスレッドプログラミング」を読むと1つのデバイスコンテキストに 複数から描画するのはまずい、とあり、実際、プライマリスレッドが 作ったデバイスコンテキスト(hDC)に別スレッドからアクセスしても フォント情報、背景色など、正しく情報を持って来れません。 やりたいことは、TRACE()の結果をIDEではなく、別Windowsに表示させる、 といった感じになのですが。
337 :
デフォルトの名無しさん :02/02/21 16:02
>336 PostMessageでUIスレッドにメッセージ投げれ。 UIスレッドでは、そのメッセージをうけて、何か描画すれ
339 :
デフォルトの名無しさん :02/02/25 23:24
リエントラントでない rand() をマルチスレッドで使いたい場合みなさんどうしてますか? あとpfintf()はリエントラント? デバッグように出したりしてるんですが
randはだめでしょ。 どうしてもつかいたければ単体の乱数発行スレッドでメッセージ通信とか すれば良いと思う。 printfはふつー再入可能じゃないのかなあ。まあ処理系に依存するよ。
rand()? リエントラントでないならロックすれば言いだけじゃないの?
343 :
名無しだけれども :02/02/26 08:37
>>339 > あとprintf()はリエントラント? デバッグように出したりしてるんですが
printf()はstdoutが共有リソースだから、
競合するようなら排他せざるを得ないでしょう。
printf()毎にライブラリがジャイアントロックする環境なら、
アプリ作成者がやる必要はないけど。
(ただしそのことをリエントラントとは呼ばない。MT-Safeではあるが)
fprintf()であれば、出力先が違う場合があるわけだから、
MT-Safeでかつリエントラントである実装が最近は多いはずだけど。
いずれにせよ、使っている環境のマニュアル読むこと。
func () { // MT-Safeではあるが、リエントラントとは言わない。
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // ジャイアント
pthread_mute_lock(&lock);
ほげほげ;
pthread_mute_unlock(&lock);
}
rand()の目的からいえば、別にlockしなくてもいいのでわ? とかいってみる。l
同じ乱数を再現する必要があるんじゃないの? 対戦テトリスとか。
346 :
デフォルトの名無しさん :02/03/16 22:34
sleep()で眠らせてるスレッドを強制的に起こす、またはそのスレッドを強制的に終了 させる良い方法ないですか?
347 :
名無しとは? :02/03/16 22:53
sleep()はやめて、pthred_mutex_lock()等で待て。 > そのスレッドを強制的に終了させる 極めて有害。
348 :
デフォルトの名無しさん :02/03/16 22:59
>>347 一定時間止めておきたい場合はどうするの?
pthread_mutex_lockで待つのはいいとしても。
>>347 >>348 ptheadでもなんでもいいです。一般的にどうするのがいいのかなと…
やりたいのは一定時間眠らせておきたい(止めておきたい)んだけど
終了させたい時にはすぐにそのスレッドを終了させたい。
pthread_mutex_lock()の場合ロックハンドルを待つということは別途
一定時間を計るタイマーを持てと?タイマースレッドの実装って美ジ
ーループでしょ?やだな。
351 :
デフォルトの名無しさん :02/03/16 23:15
pthread_mutex_timedlockがあれば使う 無ければptherad_cond_timedwait
複数のmutexを同時に、あるいはどれか一つを取得するにはどうすればいいですか?
353 :
名無しとは? :02/03/16 23:32
>>352 1. pthread_cond_*()を使う
2. 通知する側が条件を調べて真の時に通知するようにする。(condと基本的に同じ)
3. 条件を調べて通知するthreadを作る。
354 :
デフォルトの名無しさん :02/03/22 17:25
あげ
355 :
デフォルトの名無しさん :02/04/13 23:58
UNIX板では答えが貰えなかったのでこっちで質問させて下さい。 FreeBSDの<pthread_np.h>に以下の関数が宣言されています。 int pthread_attr_setcreatesuspend_np __P((pthread_attr_t *)); int pthread_multi_np __P((void)); int pthread_resume_np __P((pthread_t)); int pthread_single_np __P((void)); int pthread_suspend_np __P((pthread_t)); int pthread_mutexattr_getkind_np __P((pthread_mutexattr_t)); int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *, int)); void pthread_set_name_np __P((pthread_t, const char *)); int pthread_switch_add_np __P((pthread_switch_routine_t)); int pthread_switch_delete_np __P((pthread_switch_routine_t)); int pthread_main_np __P((void)); これらの関数が何をするものなのか知っていたら教えて下さい。
FreeBSDならソースが読めるだろ。 後に_npついてるのはPOSIXに規定されてないと思う。
>>356 今、MSのFreeBSD向けCLIがLinuxでも動作するよう移植してるんですが、
PALのスレッドの辺りが上手く動かないからちと困ってます。
FreeBSDのmanpageにもでてこないし、検索してもまったく引っかからないし
やっぱりソース読むしかないかなぁ。。
358 :
名無しとは? :02/04/14 07:44
>>355 _npってのは、NOT POSIX。
だからpthread_np.hってのは、pthread関連ではあるが、
POSIXのpthread規格に入ってない関数等のheader。
// pthread_*_npって命名自体POSIXに規定されてるんじゃなかったかな。
>>358 _npはnot portableだと思ってたが。
360 :
デフォルトの名無しさん :02/04/15 12:39
2CPUが全く同時に同じところにアクセスしたらメモリはぶっ壊れますか
「まったく同時に同じところにアクセス」することを許すような イカれたメモリコントローラの下では、 「まったく同時に同じところにアクセス」しなくとも、 メモリが煙を吐いて壊れるのは予想しうる事ではないでしょうか。
はい、ぶっ壊れます。
363 :
デフォルトの名無しさん :02/04/15 12:55
マジですか。ぶっ壊れますか。
それは大変だ。
Windowsでそれは有り得る?
みんなイジワルだな(w
367 :
デフォルトの名無しさん :02/04/15 13:37
僕は意地悪されてたんですか。
>>361 さんの書き込みで安心してたんですが、
これも意地悪なのですか。
普通は「まったく同時に」なんかアクセスされないようになってるから大丈夫。
安心しますた。
不安です。
372 :
名無し人間 :02/04/17 01:24
>>360 は、
・"one writer, some readers"
・atomic
・cache coherent
って概念を勉強して自分で考えられる人間になるか、さもなくば、
自分の知りたい場合について詳しく説明しながら質問すること。
>>372 それらを勉強するのに適した書物等あれば、おせえてください
374 :
デフォルトの名無しさん :02/04/30 06:50
Apache2.0の正式リリースあげ!
375 :
デフォルトの名無しさん :02/04/30 11:36
マルチスレッドって、2穴同時挿入とかそういうイメージですか?
376 :
名無し人間 :02/04/30 13:50
377 :
デフォルトの名無しさん :02/04/30 16:05
378 :
名無し人間 :02/04/30 20:19
>>377 むっちゃ面白いよ。Javaやらない人も一読の価値あり。
>>372 とは違って、ソフトウェア設計の話だけどね。
保守
380 :
デフォルトの名無しさん :02/05/24 19:30
質問です。 WinsockAPIを使おうと思うんですが、 これってWSA~ 以外の関数もMT-Safeなのですか? MT-Safeのこともよくわかっていないので、もしよろしければ、 MT-Safeの定義を教えてください。
>>380 へー、WindowsでもMT-Safeっていう概念あるんだ。
SolarisでMT-Safeと言ったら、複数のスレッドから同時に呼び出しても
安全で、かつそれなりのconcurrencyで動くことを言う。
全体をロックしちゃって、1度に1つのスレッドしか入れないように
なってるやつは「Safe」と呼ぶ。
reentrantだったらMTSafeだろ
>>381 の言ってることが変だと思う俺は素人ですか。
>>381-382 おお。ありがとうございます。
複数のスレッドで安全に動けばとりあえずMT-Safeということですよね?
過去ログでのWinsockのことと、CygwinのライブラリがMT-Safeでないとか、
Googleったら出てきたんで、不安になって聞いてみました。
(MSDN Libraryにも資料ないですし。)
ご教授ありがとうございます。
>>381 >へー、WindowsでもMT-Safeっていう概念あるんだ。
ってとこじゃないですか?
おれは
>>383 じゃないですけど
>>386 Safe, Unsafe, MT-Safe, Async-Signal-Safe, Fork1-Safe
という分類はSolaris独自かと思ったんですが。
Winでも同じ定義かどうかは正直知りませんです。
少なくとも一般では(Solarisは死欄)MT SAFEは 複数のスレッドからどんなタイミングで呼び出されても 正常に動作することが保証されていることを指す
>かつそれなりのconcurrencyで動くことを言う。 そんな説明はmanにありません
391 :
デフォルトの名無しさん :02/06/19 07:41
WIN32質問です。 ミューテクスと自動リセットイベントは何が違うのでしょうか。 先生方、どうかご教授を
mutexでの所有権を放棄するかわりに、EventをSetすることで mutexと同じような動作をすることも、できないわけではない。 おそらく「自動リセットイベント」は、この際に疑似所有権を 譲渡されるタスクを1つに限定する(のでmutexと同じ)と いうことだろう。 ただそうすると、mutexでは、それを所有しているタスクが 何らかの事情で死亡したときに、所有権がOSにより放棄される (=他の生きているタスクに渡る)のに対し、Eventによる 疑似所有権は、(放棄が明示でしかありえないがゆえに) 放棄されず、きわめてまずい事態(所有権の喪失=永久待ち)を 引き起こす恐れがあるので、おすすめできない。 民名書房刊、「Auto Reset EventによりMutexは不要か」
先生、よくわかりました。 先生頭よすぎです!
民名書房かよ。
>>392 Windowsはスレッドが途中で氏んでもMutexを開放しない罠。
396 :
デフォルトの名無しさん :02/06/19 23:59
MSDOSでマルチスレッド(もどきでいいので)のプログラム作るにはどうしたら言いの? だれかおしえてくらさい。
setjmp/longjmp
398 :
デフォルトの名無しさん :02/06/20 00:05
>>397 やはりそれしかないか・・・
ためしたんだけど、longjmpしたあとのreturnとかがうまくいかないです。
>>398 んじゃ、タイマ割り込みを使って自前でコンテキストスイッチ
400 :
デフォルトの名無しさん :02/06/20 00:20
スレッドってコンテクスト切り替えてるんですか? その場合、切り替えのタイミングは大麻割り込み??
>>400 大きく分けてユーザーランドのスレッドと、カーネルサポートのスレッドがある
その中でも実装によって異なるかもしれない(特にユーザーランド)
あとは本などで勉強してね(はぁと)
>>398 「うまくいかない」とだけ書かれてモナー。
とりあえずvolatileが必要に1000setjmp。
>>398 というか、setjmp/longjmpがどうやって動作しているのか理解してる?
コンテキストスイッチをsetjmp/longjmpでやるんなら、
まず自前で複数のスタックを確保して、jmp_bufを初期化してやんなきゃ。
とにかく最低限レジスタとスタックの保存と切替ができるようにしないとな。
本格的にやるならシグナルハンドラとかマスクとかも考えなきゃならんが。
>>403 一応生成されたアセンブラコード見てなんとなくは理解しますた。
だけど、コンテキストスイッチとかサパーリです。。。
まだまだ勉強不足です。
出直してきます。
レスくれた人ありがとう
>>396 文章からすると小学生くらいだと思うが、答えてやろう。
MS-DOSのコマンドではプログラムは作れません。
Javaでも、VC++でも使えば幾らでもスレッドプログラミングできます。
GUIを出したくなければ、GUIを使わなければいいだけで無関係。
>>395 ちゃんとWAIT_ABANDONEDで帰ってくるが。
クリティカルセクションなら解放しない。
MSKK SQLのマーケが10年以上まえのトレンドを
気が狂ったように宣伝しています。
http://www.microsoft.com/japan/sql/choice/ 並列処理ではマルチプロセスよりマルチスレッドの方がすべての面で
優れていると主張しています。で、最後にOracleよりMS SQLのほうが優れてる
と書いています。ヒャッヒャッヒャ。
マルチプロセス・マルチスレッド・マルチファイバ・ステートプログラミング、
どれが優れているのか・開発しやすいのか、語ってください。
マルチスレッドです。 ひたすらダーティーに。
>>408 そういう場合、Oracleより劣るところはどこか聞いてみると良い。
スレッドをバカにするとSolarisマンセー野郎に怒られますよ。
マルチスレッドは、デバッグ辛いのよね、正直。
設計が悪い
一つのオブジェクトに複数のスレッドが非同期にガシガシアクセスするという 設計のコードをデバグさせられそうになったのですが 逃げました
>>414 は、開発もできないしデバグと言う名のテスト要員にもなれませんでし
た。まあ,プロジェクトとしては助かったけどね。
保守
保守
418 :
デフォルトの名無しさん :02/08/09 00:55
ほしゅ
一周年記念カキコ
421 :
デフォルトの名無しさん :02/08/18 03:54
息の長いスレだね。 スレッドよりはコルーチンで作りたくなることが良くある。
win2kってworker thread/thread poolingがアプリから自由に使えるのな IOCPの俺様実装とかできそうな感じ
423 :
デフォルトの名無しさん :02/08/30 01:32
よろしか上げ
BCC5.5のコンパイラで32ビットのマルチスレッドアプリを作りたいんだけど、 Error: 外部シンボル '_main' が未解決(C:\BORLAND\BCC55\LIB\C0X32.OBJ が参照) のエラーが出ます。 ソースは実験のためのシングルスレッドのスケルトンです。 bcc32 -W test.cpp ではコンパイルできます。 DLLのソースなら bcc32 -WD dll.cpp でコンパイルできました。 スケルトンで bcc32 -WM test.cpp で、'_main' が未解決っていうことは、マルチスレッドならWinMain() じゃなくて、別の関数名なんですか?
425 :
名無し人間 :02/08/31 10:27
>>424 WinMainって一体なんなのか調べてみれ。mainとの違いを。
'_main' が未解決っていうことは、main()が無い って注意されていると思ったから、ハローワールドの ソースで、bcc32 -WM hello.cpp ってやったらコンソールのマルチスレッドがコンパイルできました。 32ビットコンソールなら bcc32 -WC hello32.cpp でできました。 BCC5.5では32ビットマルチスレッドのアプリは作れないんですか?
ここもレベル低いね。こんな簡単な質問に答えられないの?バッカみたい。 板ごと削除依頼しよっか?
簡単だったら何で質問するんだよ・・・
'_main' が未解決っていうことは、main()が無い って注意されていると思ったから、ハローワールドの ソースで、bcc32 -WM hello.cpp ってやったらコンソールのマルチスレッドがコンパイルできました。 32ビットコンソールなら bcc32 -WC hello32.cpp でできました。 BCC5.5では32ビットマルチスレッドのアプリは作れないんですか? 激しく( ´_ゝ`)フーン
おいおいレベルさがってるぞ〜。 おばいくーん、こまるなー、ほんと、いるよねー、こーゆーひと
429と430は同一人物。 BCC5.5を使ってない人には聞いてないいょぅ。
だから、知らねー奴には聞いてないってば。 だいたいなー、ボーランドへの質問は18cm未満の人は 質問禁止なんだよ。知りたいならオマエが聞け。
>18cm ティムポの長さですか?
おぱいだからアンダーとトップの差では?
BCC5.5ではマルチスレッドでもシングルスレッドでも コンパイル時のオプションは必要ないと分かりました。 bcc32 -W test.cpp で32ビットGUIマルチスレッドもできました。
・・・ホームラン級のバカ?
基本がわかっていないので教えてください。 お願いします。(Win32環境です) int G = 0; void init_G(void) { if(G == 0) { if( バージョン判定式 ) G = 1; else G = 2; } } 上記のような場合でもやはり init_G()内の処理は 排他を考える必要があるでしょうか? 複数のスレッドが、あらかじめ init_G()を呼び出した後で グローバル変数Gを読み取りのみに使います。(書き込みはしません) また、バージョン判定式 の部分は どのスレッドから 何回評価しても同じ結果を返し、かつ この判定自体はスレッドセーフであるとします。 同時読み書きや同時書き込みが発生するが、 メモリ上のデータの整合性(一貫性)は保たれるので 排他の必要はない と考えるのは間違いでしょうか。
>>442 考え方はあっている。
書いてあるプログラムも、「いったん判断式を評価したら、二度と評価しない」
となっているので、その点もよい。
(バージョン判定式)が ・何回行っても処理に問題はなく ・スレッドセーフであり ・常に同じ値を返す のであれば、排他制御は必要無い(はず)。 一般には(上記のどれかを満たさないorコストがかかる場合)、Gをvolatileで宣言しておいて void init_G() { if (G == 0) { lock(); if (G == 0) { if (...) { G = 1; } else { G = 2; } unlock(); } } } のように、初期化が必要になる可能性がある場合のみ、 ロックしてから再度判定する場合が多いと思う。
>>443 ,444
どうもありがとうございます。
基本的な考えは間違っていないようで、安心しました。
> 書いてあるプログラムも、「いったん判断式を評価したら、二度と評価しない」
> となっているので、その点もよい。
この理由がよくわかりませんでした。
私が if(G == 0) を付けたのは、
「判断式を評価する時間がもったいないから」というだけで
深い意味はなかったのですが、
他にも意味があるのでしょうか?
(判断式を何度評価しても動作に支障がない場合)
また、444 さんのコードの意味もよくわかりません。
void init_G()
{
lock();
if(G == 0) {
if (...) G = 1;
else G = 2;
}
unlock();
}
だけではまずいでしょうか?
lock() にかかる時間的コストを考慮?
lock() と unlock() が対になっていない点も疑問です。
ごめん。unlockの位置は{}とインデントをつけた時にミスった。 G==0を2度やっているのは、コストの問題。 本当にlockする必要があるのは最初だけで、それ以降は常にG!=0なのだから、 そのためだけに毎回lockするのは時間的に無駄だから。 例えば、Singletonなんかでインスタンスを初期化/取得する場合でも、 毎回実行する部分は出来るだけ軽くすべきであり、 最初以外はlockせずに値を取得出来るようにするため。
よく見たら、 >lock() にかかる時間的コストを考慮? って書いてあった。その通りです。
どうもありがとう。
C/C++でも、volatileは必要無いのかな?
つまり、lockした後の再判定時に、コンパイラの最適化で
レジスタ等にキャッシュされた値を読んでしまうのを防ぐ必要があるかなと。
コスト的にも、C/C++なら、スタック以外の変数(の読み出し)にかかるコストは、
volatileでもそう変わらないと思ったし(読み出しが一回だけの場合)。
Javaなら、インスタンス変数をキャッシュする関係で差がつくのはわかるけど、
>>444 は元々C/C++を想定していたから。
ただ、スタック上の変数の場合は、C/C++でもレジスタ割り付けの関係で差が付きそう。
あと、問題があることは知らなかった。
操作対象がatomicに操作できなくても、判定するためのフラグを用意すれば
一般的に解決できる問題なのかな?
とりあえず、リンク先読んでみる。
とりあえず、マルチプロセッサ環境において、 ・コンストラクタが実行されて初期化されるまでの間 ・(C/C++などのCPUキャッシュの同期が保証されていないものでの)メモリからの読み出し時 に問題があることはわかった。 その他はまだよく理解出来てないけど。
>>444 どうもありがとうございます。
おかげ様で大変よくわかりました。感謝感謝です。
今度は
>>448 の
volatile宣言の必要がないというのがわかりません。
(444さんと同じ考えですが) volatileが無いと、
lock とunlock が通常の関数呼び出しとして実装されている
なら大丈夫としても、
仮にこれらがインライン展開される関数やマクロだった場合に、
・lockの直後のif文で G がメモリから再ロードされるかどうか
・更新後の Gの値がunlockの前でメモリに書き込まれるかどうか
が保証されないのでは? と思えます。
452 :
デフォルトの名無しさん :02/09/01 23:27
>>451 たとえば
mutex L;
int data;
として、スレッドAで
lock(L);
dataに代入; // …(1)
unlock(L);
とした後、スレッドBで
lock(L);
dataの利用; // …(2)
unlock(L);
ってしたとき、たとえvolatile宣言がなかったとしても
(2)において(1)の変更が見えないのはマズイ。
だから、
> 仮にこれらがインライン展開される関数やマクロだった場合に、
> ・lockの直後のif文で G がメモリから再ロードされるかどうか
> ・更新後の Gの値がunlockの前でメモリに書き込まれるかどうか
> が保証されない
なんてことがあったら、それはスレッドライブラリ側のバグ。
さらに、緩いメモリモデルをとっているアーキテクチャ上の
スレッドライブラリではlock, unlockの際に適切なメモリバリア命令を
実行していたりもする。
IA-32ではメモリ書き込み順やキャッシュ一貫性の保証があるんで
こういう話とはほとんど無縁だけど、pthreadの本とかでは
ここらへんが重要な話として載ってるよ。
>>452 > それはスレッドライブラリ側のバグ。
> さらに、緩いメモリモデルをとっているアーキテクチャ上の
> スレッドライブラリではlock, unlockの際に適切なメモリバリア命令を
> 実行していたりもする。
これは標準Cから逸脱している特定のシステムの話では?
>>453 当然逸脱してるけど、それを満たしていなかったらスレッドライブラリとして
使い物にならないって言う事じゃないの?
違ってたらスマソ
455 :
お役立ちサイトです。 :02/09/02 00:18
>>454 >>452 =458だと思てるんで、
> そのコードだとGをvolatile宣言する必要はナシ。
も含めてちと言い過ぎじゃないのかなと。
>>452 なんとなくわかりました。
たとえvolatileがなくても、lock/unlock の前後では必ず
メモリに反映されるような実装になっている(はずである)。
ということですね。
どうもありがとうございます。
>>456 ちょっと言い過ぎだったかもしれんが、
もしvolatile宣言が必要な処理系があったとしたら、
>>454 の言うように「スレッドライブラリとして
使い物にならない」のは確か。
ポインタをvolatileと宣言しても、その指し示すデータは
volatileにならない(ちょうどconst宣言と同じ)から、
リストとか木とかちょっと大きめのデータ構造を
ロックしようとしたときにえらく面倒になってしまう。
つまりJavaのスレッドは使い物にならない、と。
462 :
デフォルトの名無しさん :02/09/05 00:35
pthreadのpthread_t(スレッドハンドラといういい方でいいのかな、WIN32だと ハンドラというけど)型の変数や、pthread_cond_t型の変数を他のint型やchar型 のデータ構造体の中にいっしょに詰め込んでmallocして使ったらメモリー破壊 されまくり。ポインタにして分けてmallocしたらうまく動きますた。 何故何故??
ハンドラとは言いません。ハンドルとはぜんぜん意味の違う言葉です。
464 :
デフォルトの名無しさん :02/09/05 01:19
つかぬ事をお聞きしますが、 マルチスレッド処理が必要なときって何?
>>462 > 何故何故??
あなたの書いたプログラムにバグがあったから。
>>462 pthread_t
pthread_cond_t
だけ?
pthread_mutex_tがなきゃpthread_cond_tは意味を成しませんが。
どのような使い方をしているのか理解出来ないのですが・・・
>>464 必要な例:
いわゆるUNIXでは、fd(pipe/socket等)のポーリングと、sysv IPCの同期待ちと、
プロセス終了待ちと、pthreadの同期待ちを単一のスレッドで同時にはできない。
これは個別にスレッドを立てるしかない。
これ以外は再利用の都合じゃないでしょうか。
独自のループを持つ既存のモジュールを使いまわせるとか。
>>464 467の他に「CPUが複数あるマシンで速く計算するため」というのもあるな。
469 :
デフォルトの名無しさん :02/09/11 17:56
どうと言われても・・・
シラネーヨ
>>471 XEON買え、買えないなら諦めろ。
以上
そこでほとんど語られてんじゃん。
mutexを2種類使うケースってどんな場合があるのでしょうか?
すみません。質問の仕方がまずかったかも pthread_mutex_t 型のmutex変数を2つ以上使う場合ってどんな場合なのかなと 思いまして質問しました。
>>477 リソースが複数ある時とか。
セマフォと同じ用途。
マルチスレッドの入門書でも読んだ方が早いな
2つ以上必要な時はデッドロックに気をつけてな
>>480 確かにアタマが割れるようにイタイ!!!!
それはヘッドロック
てへ★ミ
>>467 > sysv IPCの同期待ちと、
> プロセス終了待ちと、pthreadの同期待ちを単一のスレッドで同時にはできない。
スレッドを使わずとも、selectや、sigactionを使って同期を取れますが・・?
> これ以外は再利用の都合じゃないでしょうか。
> 独自のループを持つ既存のモジュールを使いまわせるとか。
その糞モジュールが本当にスレッドでまともが使えるのか結構疑問にかんじますが。
>>486 > 467の他に「CPUが複数あるマシンで速く計算するため」というのもあるな。
た、たとえばどんな?
計算させたって、計算終わるまで結果待ちしてるヤシがいるのはずだけど、そいつは何してるの?
画面描画?画面描画のための計算処理が重いのではないのか?
「Windowsプログラミングでメッセージ処理とソケットの同期がスレッドでないと取れない」ぐらいしか漏れには思いつかない。
芳しいのが登場したからsage
484 :
デフォルトの名無しさん :02/09/16 23:45
gcc-2.96, glibc2.2上でMTなプログラムを書いています。そろそろプロファイラにかけたい と思い、-pg付きでコンパイル・実行してみたのですが、gmon.outが出力されません。 プログラムは、^Cで止めるまで動き続けるものです。どうやらexit()がgmon.outを書き出す らしいとわかったので、sigactionでSIGTERMをハンドルするようにしましたが、駄目でした。 なにか知恵をください。
>>484 SIGTERMはSIGINTの誤記です。ちなみに^Cではなく、
killall -INT program_name にしてます。
>>484 pthreadはよく知らんのだが、
#include <stdio.h>
#include <signal.h>
void h(int x){ exit(1);}
int main(void){ signal(SIGINT, h); while(1); return 0; }
漏れの環境では、single threadの上のは^Cでgmon.out出る。
>>486 似たようなコードでも、MTにしたとたん出ないです。
488 :
デフォルトの名無しさん :02/09/17 00:36
マルチスレッドとマルチプロセスってどう仕組みが違うんですか? このバカに教えてください。
主に同じアドレス空間で動くかどうか
>>488 バカに理解させるのは疲れるのでいやです
バカのお蔭で俺の質問が消えてく…
495 :
デフォルトの名無しさん :02/09/17 01:00
496 :
デフォルトの名無しさん :02/09/17 01:07
アドレス空間。 あるアプリケーションが h0番地からhn番地までのメモリを使える時、 h0番地~hn番地までの範囲が、そのアプリケーションのアドレス空間。 プロセスp1とプロセスp2のアドレス空間は全く重ならないけど、 スレッドt1とスレッドt2のアドレス空間はぴったり一致する。
>>495 ?
アドレス空間が完璧ってどういうことですか?
>>496 ありがとうございますm(..)m
禿しく理解できました。
ついでにこれも聞いていいですか?
本を読んでWIn95はプリエンティブなマルチタスクでは無いとかなんとか
と書いてありました。
これはどういうことですか?
>498 今さらそんなことが書いてある本があるのか? Win95はプリエンティブなマルチタスクですよ。 つーか、ム板民なら、そのくらい解れ。
preemptive a(形容詞). 先制(攻撃)の; 先買権のある. preemptively ad(副詞). 投機実行があるという意味でしょう。 メモリに存在している複数のスレッド(一部は特定の仮想マシンを共有している) 間の投機実行が行われるという意味。実行中のスレッドを一時停止させ 別のスレッドを投機実行させる。non-preemptiveな場合はそういうことは ない。ま、win3.1にはスレッドという概念すら無いに等しいが。
501 :
デフォルトの名無しさん :02/09/17 01:55
ハァ?
ひぃ?
いやん。
>>499 Win9xはプリエンティブなアプリとノンプリエンティブなアプリが
混在するから、不完全なプリエンティブマルチタスクと言われていたはず。
>>482 遅レスだが・・・
MsgWaitForMultipleObjectsとWSAEventSelect使えばメッセージ待ちながらソケット待てるよ。
Win32だとWSAEVENTは単なる手動リセットイベントだから。
Overlapped I/O使うならMsgWaitForMultipleObjectsExね。
>>494 つーか、Linuxなの?
だったらmain threadのpidにだけkillしてみれば?
>>504 あと、動的プライオリティ計算がせこいのも、
プリエンプティブスケジューラとしては貧弱でしたな。
ブーストと言われても…
508 :
デフォルトの名無しさん :02/09/17 23:24
今まですっとWinなスレッドしか使ってなかったけど linuxのpthreadってなんか使いにくくてしょうがない
>>509 自由にぼやいて貰って構わないんだけど、
「Winなスレッド」って生CThreadのこと?
512 :
デフォルトの名無しさん :02/09/18 16:35
キモイの定義ができない人はム板にはいりません
514 :
デフォルトの名無しさん :02/09/19 23:26
あげ
>>505 おお そんなものがあるのですが、Win厨で失礼いたしましたぁ!_O_
しかし、ますますマルチスレッドプログラミングの必要性を見失いつつあり…。
最近はマルチスレッドプログラミングで苦悩している人を見ていると、とてもかわいそうなわけで…。
>>515 マルチスレッドプログラミングは、やればやるほど
スレッドを減らす方向に設計したくなるという面白い側面がありますね
_beginthreadex() が返すハンドルは CloseHandle() APIで閉じなければ ならないという事なんですが、CloseHandle() を呼び出す位置は _endthreadex() が (明示的もしくは暗黙的に) 呼ばれる前、呼ばれた後の どちらでも構わないんでしょうか。
ハンドルは参照カウンタで管理されてるからどちらでもよい 不要だったら生成直後にcloseしてもよい
520 :
デフォルトの名無しさん :02/09/26 14:16
マルチスレッドのプログラムについて質問があります。
諸兄の知恵を貸してください。
現在、Solarisベースでpthreadを使用したプログラムを作成しています。
これはバックグランドで動作させ、デーモンとして使用するものです。
生成したスレッドの内部では、動的にメモリの獲得・解放を繰り返すのですが、
ps -el でSZの項目を監視すると、数値が増加しつづけてしまい、減少しません。
Purifyもかけてみましたが、リークはありませんでした。
原因を調べるためwebを検索したところ
ttp://www.ncad.co.jp/~komata/c-kouza28.htm このようなサイトを見つけました。
>スレッド内で動的に多量のメモリを確保すると、プロセスサイズが大きくなり、戻らない
とあるのですが、これは「スレッド内部でメモリを確保しまくるとSZの値は減らない」と
解釈していいのでしょうか?
長文ですいません。
521 :
デフォルトの名無しさん :02/09/26 14:31
この前手伝ったプロジェクトは、Windowsのクライアントソフトに がんがんスレッドを走らせていた。5つくらい。 あるひとりの優秀である(と言われている)人が設計したらしいんだけれど、 ソースコードにコメントが無いし、独自にCOMを実装してる(実装方法はCOMそっくり) そのくせプラットフォームはWindows限定で、しかもSTLは使ってはいけなくて ……愚痴はやめておこう さて本題ですが、個人的にはリソースが絡まないのにマルチスレッドにしないで欲しいんだけど、 一体何の理由があってマルチスレッドを利用したんだと思いますか? 部外者の俺が思うに、 ・ある程度知識のあるプログラマが自分にしか理解出来ないコードを作ることで、支配基盤をはっきりさせたかった ・過去に作っていた自分のプログラムを再利用したかった(でもコードを見ると多分違う) ・クライアントマシンにマルチプロセッサの時代が来る事を見越していた(これもコードを見ていると多分違う) ・パズルが好きだった。 マルチスレッドをよく使う方々、他になんか理由があれば教えてください。
何をするクライアントか書いてないから判断しようがない windowsということで、STLを使ってDLLとデータをやりとりすると、 ランタイムの関係でメモリ周りで問題が出る場合がある あんたが差してるリソースの定義が曖昧だ、 CPUリソースもリソースであるという考え方も出来る 要するにお前は死ねって事だ。
523 :
デフォルトの名無しさん :02/09/26 15:01
相談室ということで、質問をさせてください。 今、Windowsで_beginthread()関数を利用して、経験のため無意味にスレッドを走らせています。 しかし、処理があまりにも遅くなるのでちょっと不可解に感じていました。 そこで、ループの先頭にSleep(1);を付け加えたところ、急にスムーズに動きました。 何が原因でこのような現象が起こるのでしょうか?
一つのプロセス内にあるスレッドがどれも必死で CPUを使おうとしているから、 OSがその競合を解消しなければならなくなる。 ↓ Windowsはそんなに賢くない。 ↓ 遅い。 Sleep(1);を加えると、OSはアイドルタイムをスレッドに割り振る処理しか しなくてよいので、負担が減って早くなる。と、てきとうなことを言ってみるテスト。
>>521 我儘と傲慢が文中に溢れてるね。
久々に見たイターイ作文だな。
突っ込みどころ満載だけど、一部。
コメントが無いってのは、
「自分じゃ理解出来ないから説明しる」
STL は使ってはいけなくてってのは
「自分は STL バリバリだから使え」
スレッド使う意味があるのかってのは
「私はスレッドについては無知なので
是非使うのを止めて頂きたい」
って事か?
自分より出来る人を陥れる事に夢中になりやがって。
そいつのレベルを越える事に精進しな。
>>525 その通りかも。精進します。
しかしコメントが無いのはマジで困りました。本当に理解できないのです。
WaitForMultipleObjectsが、一体どのリソースを待っているのか確認するのは大変でした。
STL使っては行けない理由はサイズが大きくなるからだそうです。
MFCのCArrayとかを使いなさいと言われました。
スレッドを使う意味があるのかってのは、本当に解らなかったからです。
どんなクライアントかを簡単に言うと、ドロップされたjpeg画像を読み込んで、
それを横一列にサムネイルで表示するだけのプログラムでした(その当時は)。
その後、ネットから画像を読み込む様に対応させる方向にするのかもしれないですね。
その意味では予めマルチスレッドで実装させる必要があるのかもしれません。
ちょっと厨房な質問スマソでした>ALL
サムネイル作成は結構重い処理だから bgで作成してないとアプリが固まったようになってしまう って事じゃないの?
>>526 をっ、マジだったのね。きつぃ言動スマソ。
使う、使わないの理由聞いてんじゃん。
2ちゃんで聞くより、本人(SE)が暇そうな時に
もっと直接聞いたほうが間違いないと思うけどな。
まぁ、いろんな意見を集めた方がいいけど...
>>527 それだけでもないみたいです。というのも、別にサムネイルを作るところを
別スレッドにしているわけではなくて、ただサムネイルを表示する
GUIの部分の、独自メッセージのやりとりをしている部分がマルチスレッドでした。
例えば、何もないダイアログを作り、そこにボタン、スクロールバー、
エディットボックス、などなどを追加していきます(プログラムで)。
で、一斉にそれらがマルチスレッドで処理を始めるという具合です。
それぞれ普通にプロシージャを使ってWindows任せで処理すればいいと思うんですが…。
>>523 多分、他のスレッドと同期を取って計算しているんだと思うけれど、その同期の取り方が
適当なグローバル変数などを使ってやってるのではないでしょうか??
例えばスレッドAでflag=1にすると、スレッドBの処理がはじまる、というような場合、
スレッドBでは、while(flag!=1); みたいに待機しているんだと思います。
その時に、一度flag!=1を確認すれば、すぐに別スレッドに処理を移すべきなのだけれど、
もちろんOSではそんなことはわからず、ある一定の決められた期間スレッドBでは
ひたすらflag!=1を評価し続けます。この時間はまるまる無駄です。
そういうタイミングでSleep(0)を入れてやると、すぐに別スレッドに処理が移るので、
効率的にCPUを使うことが出来る、という現象だと思います。
(この場合、Sleepは1でなくて0で問題ないはずです)
どうでしょうか?
>>521 そいつはやる気のある天才だな。
自分よがりとはいえ、そこまでの技術を「たかが」仕事で使ってしまう辺り、
自分の仕事に自信があり、その会社でも正当な評価を受けてる証拠だろう。
そういうコードはめったに見れないから、素直に見習ったほうが良いぞ。
ここで聞かずに、その天才に聞けよ。(なんで本人に聞かない?)
>>529 > そういうタイミングでSleep(0)を入れてやると、すぐに別スレッドに処理が移るので、
> 効率的にCPUを使うことが出来る、という現象だと思います。
> (この場合、Sleepは1でなくて0で問題ないはずです)
「マルチスレッド 同期」あたりで、一回グクッてみることをお勧めする。
>>531 間違ってないんじゃね?
Sleepせずにビジーループで変数待機してると
割り当てCPU時間全部使うまでCPU解放しないわけだし。
同期については Windowsにはウィンドウメッセージという機構があるんだから ぜひともそれを使っていただきたいものです 下手に俺様キューを作るよりよっぽどマシです...
>>533 > 間違ってないんじゃね?
別に間違っているとは言っていない。そもそも...
>> 例えばスレッドAでflag=1にすると、スレッドBの処理がはじまる、
に対して...
>> スレッドBでは、while(flag!=1); みたいに待機しているんだと思います。
なんてことは普通しない。素直に、Event ととか使えば、スレッド B は待ってる間全然 CPU を使わない。
>>534 該当スレッドにウインドウが無い可能性もあるだろ
あと、WindowsのメッセージはHWND指定がついてくるのが気持ち悪い。
素直にイベントに汁
>>536 ウィンドウがなくてもメッセージキューとして使えることを
知らないアフォが多すぎ
>>537 勿論知ってますが。
GetMessageでHWNDの指定を強制させるのが嫌すぎというだけです。
非同期ソケットとか、トレイアイコンにも言えることですが。
強制ってのは何か違うな、、、 MSGにhwndが入っているんだから、それで良いじゃないかってだけです。
GetMessageのHWNDにNULL指定できることを知らないのか? ヘルプもロクに読めないとは・・・
送り側スレッドがPostThreadMessageで送って、 受け側スレッドがGetMessageで受けるんでしょ。 それでメッセージキューが実現できるという話だと思うんだが 何をゴネてるの?
>>540 勿論知ってるっつーの
GetMessageにHWNDがあるのが気に入らないだけ
( ´_ゝ`)フーン
>>542 気に入らないならWindows使うな( ゚Д゚)ゴルァ
545 :
デフォルトの名無しさん :02/09/27 00:47
>>529 > それぞれ普通にプロシージャを使ってWindows任せで処理すればいいと思うんですが…。
何故いいと思うのか根拠書かないと。
GUIスレッドを自前で持つなんて、
Look&Feelのレスポンスが重要な局面ではよくやることだよ。
何も不思議なことはやってない。(少なくとも提示されている条件内では)
それよりも君の
>>521 の姿勢がずっと疑問。
AFCのスレッドモデルについてちゃんと理解してるの?
>>545 >>521 >さて本題ですが、個人的にはリソースが絡まないのにマルチスレッドにしないで欲しいんだけど、
これ見る限り素人だし相手にしても無駄だよぅ
送信ミス、スマソ
>>545 MainThread: ダイアログを作る -> サブスレッド起動
Sub1: ボタンのメッセージを処理
Sub2: スクロールバーのメッセージを処理
Sub3: エディットボックスのメッセージを処理
って事じゃないの?
>で、一斉にそれらがマルチスレッドで処理を始めるという具合です。
こう書いてあるし
>>548 読み間違いに一票。
単に521が仕事できないだけだろ。
>>529 >スレッドBでは、while(flag!=1); みたいに待機しているんだと思います。
こんな事考えてる様なやつだしね(w
>>550 それは523があまりにも初心者だから、そう推測したんじゃないのか?
と、擁護してみる。
552 :
デフォルトの名無しさん :02/09/27 01:14
マルチスレッドってどういう時に使うの?
>>553 エロゲーやりながらオナニーしたいときとかだね。君の場合。
>>542 嗚呼、無能なヤシは困る…
505をお読みになったか?
どうでもいいがWaitFor〜じゃメッセージ待機出来ても取得できないぞ
>>557 WaitFor〜じゃメッセージ待機できない。
できるのはMsgWaitFor〜だよ。
それでもメッセージの取得はできないが、メッセージが届いている事を
前提にできるから、GetMessageでブロックせずに取り出せる。
>>558 GetMessageが気に入らないんじゃなくてHWNDが嫌いなんだから、
PeekMessageも当然ダメだろ。
すみません、僕のことで揉めるのは止めて貰えないでしょうか? 僕だって困ってるんです。隠居して、田舎暮ししたい…
NULL指定してても気に食わないとかいう理由で だめとか言ってるんだから単なる言いがかりだろ
>>561 > NULL指定してても気に食わないとかいう理由で
> だめとか言ってるんだから単なる言いがかりだろ
言いがかりって...、Windows マンセー野郎様ですか ?
メッセージキューは本来もっと一般的なものだから、基本的には HWND なんてものがいらない素のバージョンの API があって、ウィンドに対するメッセージは、これをラップして使えばいいと思う。
でも、Windows では大多数がウィンドに対するメッセージだから、HWND 付きのメッセージ機構のをウィンド無しでも使えるようにしたという実装も理解できなくは無い。
俺はそう言う実装は嫌いだけど、それ以外の利点が大きいから Windows を使う。ただそれだけじゃないの ?
気に入る気に入らないの問題だったらどうでもいいです
564 :
デフォルトの名無しさん :02/09/28 23:33
>>562 使うもなにも、用意されてる選択肢がそれしかないんですけど。
ハァ?自前でメッセージキュー作れますが?
567 :
デフォルトの名無しさん :02/09/28 23:39
>>565 わざわざ気に入らないからって、スレッド対応のメッセージキュー作るの?
>同期については >Windowsにはウィンドウメッセージという機構があるんだから >ぜひともそれを使っていただきたいものです >下手に俺様キューを作るよりよっぽどマシです... そういう風に作ってしまった場合、 ログオンプロンプト(パスワード入力画面)のまま、 ATコマンドやRPCでプログラムを起動したらどうなるの? これがWindowsのプログラムのヤナ部分。
なんの話?
>>568 GUIスレッドと
ATコマンドやRPC発行スレッドを
別にすりゃいいんでないの?
>>569 たとえばTVのタイマー録画のソフトを作った場合、
パスワードを入れた状態でユーザーが外出したり
することになるでしょ。
デスクトップを開いていない状態でウインドウハンドル
を操作するAPIを実行するとそこで停止するかエラーになるでしょ。
いまいちよくわからんのだが。 もしかして、関わらない方が良い?
571はエラーになることを確かめたの?
>>同期については >>Windowsにはウィンドウメッセージという機構があるんだから >>ぜひともそれを使っていただきたいものです >>下手に俺様キューを作るよりよっぽどマシです... >そういう風に作ってしまった場合、 >デスクトップを開いていない状態でウインドウハンドル >を操作するAPIを実行するとそこで HWNDにNULLを入れるからウィンドウハンドルは操作しませんよ?
575 :
デフォルトの名無しさん :02/09/29 00:04
ウインドウシステムと依存関係のあるモジュールを 使ったプログラムは、ログアウトした状態では 使えなくなる欠点があるだろ。 だから、夜間にログアウトした状態で OLEを使ってエクセルのシートを集計したりできないわけ。 端末の上でしか動かないという制約のあるモジュールは なんだかな。
576 :
デフォルトの名無しさん :02/09/29 00:06
>>571 はエラーになることを確かめたの?
NT上で確かめたよ。
サービスの作り方で、停止するかエラーかが決まる。
>>575 ちょっと飛躍するけど、user32.dllを使ったAPIやつが駄目って事?
s/APIやつ/API/
575-576
それってMessageBoxとかを出すときの話では?
元はメッセージキューをWindowMessageで代用するという話だったのに、
いつのまにすり替わりましたか?
>>572 あんたするどい
>>565 > ハァ?自前でメッセージキュー作れますが?
普通作れるだろ ?
>>567 の言うように普通は、「作らない」けどな。
>>572 俺もそう思う。
つかサービス用にデスクトップが割り当てられるだろ。
使ったこともないくせに想像でモノを書いてるUNIXプログラマ様ですか?
とか
>>572 の警告を無視して釣られてみる。
>>562 HWNDにNULLを指定すればHWNDなんてものはいらないだろ。
お前はほんとにGetMessageの引数にNULLがあるせいで困ってるのかと
小一時間問い詰めたい
単にMSの設計はセンスが悪いって言いたいだけちゃうんかと。
s/NULLがあるせいで/HWNDがあるせいで/;
>>582 > 単にMSの設計はセンスが悪いって言いたいだけちゃうんかと。
ただそれだけだけど ? (つーか、
>>562 は普通そうとしか取れないと思うが。)
誰も困ってるなんて書いてない (除く
>>560 ) んですが、妄想ですか ?
>>584 =562=話の流れを理解してないやつ?
つーかね。きみ文章ヘタ。
587 :
デフォルトの名無しさん :02/09/29 01:02
>つかサービス用にデスクトップが割り当てられるだろ。 システムからダイアログを唐突に出されたら止まるから却下。
デスクトップが唐突に出てきた背景の説明キボンヌ
589 :
デフォルトの名無しさん :02/09/29 01:07
依存関係を作るって事に対する疑問符だな。
590 :
デフォルトの名無しさん :02/09/29 01:17
>でも、Windows では大多数がウィンドに対するメッセージだから、 >HWND 付きのメッセージ機構のをウィンド無しでも使えるようにした これのソースキボンヌ。 この挙動は保証されているのかな。
すんません、話の流れとそれるかも知れませんが WindowsでGetMessage等を呼ばずにシステム互換のメッセージキューを作る方法教えてくれませんか?
Windows限定だったらwin32apiスレで聞けば?
595 :
デフォルトの名無しさん :02/09/29 01:32
>>593 MUTEXをロック
受信側は共有メモリにFIFOバッファを作る。
ポーリング時だけ開放
送信側は送信時にMUTEXをロックしようとする
→相手がポーリグするまでブロックされる。
双方向にする場合は双方でFIFOを持ったうえで
さらにデッドロックしないようにプロトコルを明確化する。
>>595 > MUTEXをロック
> ポーリング時だけ開放
> 送信側は送信時にMUTEXをロックしようとする
> →相手がポーリグするまでブロックされる。
それって一個しかデータが入らないから、キューじゃねーじゃん。
普通は、ポーリングする瞬間だけロックして、キューが空だったら何らかの同期機構で待つ。
送信側も書き込む瞬間だけロックして、キューが満杯だったら待つ様に作る。
(普通のキューと同じだと思うが...。)
入門書にでも書いてありそうなことをここでやるの?
>それって一個しかデータが入らないから、キューじゃねーじゃん。 FIFOだからキューだろうが。普通はリングバッファにするわけだ。 >普通は、ポーリングする瞬間だけロックして、 >キューが空だったら何らかの同期機構で待つ。 つまり、開けて待機することがポーリングなわけだ。 双方向だとデッドロックとかめんどくせぇ問題が起きるから なるべくサーバー・クライアント型にして、 サービス側リクエストがくるまでずーーと待機というデザインだな。 オレの場合。
>>597 つまらないと思うなら無視すればいいだろ
いちいち突っ込むなボケ
>システム互換のメッセージキューを作る方法教えてくれませんか? だれもこれを満たしてない
>>598 > なるべくサーバー・クライアント型にして、
> サービス側リクエストがくるまでずーーと待機というデザインだな。
それは、キューとは言わん。
611 :
デフォルトの名無しさん :02/09/29 05:42
まあまあ、落ち着け。お前等のおかけで、このスレが「哲学者の食卓」みたいになってるよ。 二人とも、ちょっと Sleep(100) ぐらいしてこいや。
すみなれたーわがやにー はなのかほりをそーえてー やさしくーそだったー じゅもくかほりもいーれてー このまちでーいちばんー すてきでくらしたーいー りふぉーむーしようよー しんーにほんーはーうすー
環境はLinux + pthreadで、 /* pthread_createに渡す関数 */ void* thread_func(void* arg) { int* sd = arg; /* sd: ソケットディスクリプタ */ char c; while (1) { int result = read(sd, &c, 1); if (result == 1) { fputc(c, stdout); } else if (result == 0) { usleep(WAIT_MSEC); continue; } else { perror("read on thread_func"); pthread_exit(NULL); } } } …としています。ソケットにデータが流れてきた時にreadするように書きたいのですが、 usleepを使う以外の方法はありますか?
(´-`).。oO(select知らないんだろうなあ)
617 :
デフォルトの名無しさん :02/09/29 07:14
CreateThreadで作られたスレッドには、lpParameterで指定した情報しか わたすことができないんですか? 初心者な質問でスマソ。
つーか自分でやってみりゃいいじゃん
自分でやってみてどうしようもなくなりました。 2つ以上のパラメータを渡したかったらどうするんですか?
>>617 パラメーター構造体を定義して、mallocして
そのポインタを渡すというのが常套手段ッス〜
そしてスレッドを使わないプログラムに回帰するのであった・・・ というネタが繰り返されるスレはここですか?
初心者が質問してごめんなさい。 今、エディタにプログラム書いて、コマンドプロンプトでコンパイルしてみたいな ことしているんですが、マルチスレッドってこんな環境で使えるの?VCのような 開発環境でないとダメ?
>>623 開発環境は関係ない。
というか関係があるのかどうか自分で判断できるように努力しる。
>>614 ,615
select知りませんですた(´・ω・`)ショボーン。ありがとう。
627 :
デフォルトの名無しさん :02/09/29 23:16
プログラムは、理論を学習するのと、理論なくしてプログラミングを実践するのとどっちが重要ですか。
>>627 マジレスするとどっちも重要。
実践して壁に当たってから理論せれ。
壁に当たらんと、理論のありがたさがわからん。
質問。 スレッドをいくつか作成して、 メインスレッドが各スレッドにPostThreadMessage、 サブスレッドはGetMessageでそれを捌く。 これを数万〜数十万オーダー繰り返すとたま〜にGetMessageがデッドロック起こす現象に悩まされたことがあるんだけど、 他にそんな人いる? すっごいシンプル(100行未満)なテストプログラムでも起こったんで、何か原因があるとは思うんだけど見当つかなかった。
>>617 ,619
構造体のポインタか、クラスのポインタわたせば?
>>634 s/構造体のポインタ/構造体のインスタンスのポインタ/
s/クラスのポインタ/クラスのインスタンスのポインタ/
>>632 while(GetMessage(&msg,NULL,0,0))
とかやってないよね
>>636 いけないの?
どこのサンプルでも-1をチェックしてないようだけど
ども。 数年前の話だったので久しぶりにソースおこして確認してみました。 その結果、PostThreadMessageで10001個目のメッセージをPostするとエラーが返っていたことが判明。 GetMessageはエラーを返さず、GetLastErrorも0を返していたけれど 単純にメッセージキューのオーバフローが原因だと思われます。 前回はエラーチェックが甘かったのかな。 結局自前でスレッド間メッセージキューを実装してしまいました。 まぁその経験がその後の仕事で活かされた(pthread使う仕事があった)ので 自分的には結果オーライでしたが。
-1が失敗であって、-2が成功とも言えるからチェックがめんどくさいな
>>640 かつてのSetMessageQueueSizeの説明には
ポストできるメッセージの数に上限はなくなったとか書いてたのに
なんかインチキくさいな
つか回数制限を知らないヴァカがいることが驚き。
>>642 ×SetMessageQueueSize
○SetMessageQueue
上限がなくなったとは書いてない。
必要に応じて拡張されるようになったと書いてある。
Win2Kにおける既定の拡張限界が10,000ということ。
メッセージを取り出さないで10000個Postしたって事? 普通にアプリケーション組んでれば、10000個以上のメッセージの送受信普通だが。
10000個も滞留するのが普通なのか・・・
>>644 10,000個以上の必要には応じてくれないんですか?
やっぱ強引というかMSに好意的過ぎる解釈だと思う。
古いPostMessageのヘルプにはこんな制限書いてなかったし
>>647 >10,000個以上の必要には応じてくれないんですか?
ヴァカ発見(プ
>>647 何事にも制限はある。
どうしても、
10000個以上のメッセージを溜める糞ソフトを書きたければ、
レジストリを修正しろと書いてるだろ。
あと、この10,000という数はWin2kにおける数値だから、
Win2kが出る前の古いヘルプに書いてあるわけがないと思われ。
>>649 Win2000以前には制限がなかったのに
突然制限つけてドキュメントのほうまで変えるのが納得できない。
今まで95/98/NT4で動いていたプログラムが
動かなくなるってことでしょ。
>>650 試してみた?
手元にあったWin98マシンで試すと、
1000くらいが限度みたい。
95/NT4は手元にないので試せないけど。
>>647 おまえみたいなアフォがゴルァして来てウザいから追加されたんだろ。
ここは強引なAPIの変更、それによるソフトウェアの構造の変更を 強いられることをありがたがるオメデタイMS信者しか居ないようですね。 こういった変更が無いことが保証されている環境は存在しないのでしょうか。 もうこれ以上馬鹿を見るのはごめんです。
致命的なバグがあっても改善されない環境を 望んでいる変人がいるすれはここですか?
WinのAPIが安定しないことは確かだが、
>>644 ,649はどうみても妥当。セマンティクスは厳密になり、
しかも上限は変更可能になっている、ということで言い掛かりだと思う。
と
>>653 に釣られてみる。
win界隈はドキュメントされてるだけマシっつう話もアルヨ・・・
LinuxやFreeBSDなら「ソースを使え、ルーク」なのだろうが Appleとかどうするんだろ
>>657 とりあえずDarwinのソースでまあなんとか。
え? Mac OS < 9ですか? およびでない? 失礼しました〜。
>>657 >「ソースを使え、ルーク」なのだろうが
ワラタ
windows上C言語でプログラミングしてて、マルチスレッドを使おうとしてます。 CreateThread()を使おうと思ってるのですが、作成したスレッドには一つしか引数を渡せないのでしょうか? 複数の引数を渡したいのですが・・・
653と名のってますが間違いですw
662 :
デフォルトの名無しさん :02/10/04 22:23
クイックソートをマルチスレッドで書いたら速いので教えてください。
>>662 並列アルゴリズム ソート
でgoogleしてみよう!
つかCPU数が2以上じゃないと多分効果ないと思う
666 :
デフォルトの名無しさん :02/10/05 00:32
Windowsでプログラムしてマルチスレッドを使おうとしています。 BeginThreadを使おうと思っているのですが、作成したスレッドには1つしか引数を渡せないのでしょうか? 複数の引数を渡したいのですが・・・
これは何かの陰毛なのか?
構造体、、
ネタは放置
>>442 大昔の話をいまさらだけど、素朴な疑問。
それらのスレッドが動き出す前に1回init_Gを呼んでおく
(そして各スレッドでは呼ばない)
ってわけにはいかないんですか?
まあそういかないから質問してたんでしょうけど。
>>672 ・init_G()が呼ばれるかどうかは事前には判らない
・init_G()の呼び出しは少なからず何らかの常駐リソースを食う
(DLLのロードやメモリアロケート等)
という前提ならああしたくなるでしょうね。
なんとなく浮上
675 :
デフォルトの名無しさん :02/10/13 08:22
あるスレッドに文字配列を渡そうとして以下のようにやってみて、受け取り成功したのはいいのですが このPostThreadMessageしたときに渡したローカル変数bufは、自動的に解放されますか?(受け取りで何かする必要あり?) //送信側 char buf[]="ゴルァ"; PostThreadMessage(idThread, WM_USER+10000, (WPARAM)buf, 0); //受信側 GetMessage(&msg, NULL, 0, 0);
自動変数なら、関数から抜けたときに開放される。 そういうう変数をPost〜で渡すのは、不確実性の元。 渡してはいけない。
677 :
675の上司 :02/10/13 15:52
>>675 バカ野郎!そんなコード納品したらクビにするぞ!
二度とするなよ。いいな?
どうしてもやりたきゃ、こうしろ。
PostThreadMessage(idThread, WM_USER+10000, (WPARAM)"ゴルァ", (LPARAM)"
>>675 の上司より");
678 :
デフォルトの名無しさん :02/10/14 04:11
Javaでタイムアウト付きのwait()した時に、notify()されたのか、 タイムアウトしたのかを判断する方法知ってる人いる? つーか、何でタイムアウト付きwait()の戻り値がvoidなの?
679 :
C ◆dq2PerGLN. :02/10/14 04:31
CFileのMFCにあるファイルを開くダイアログはC#だとどのクラスでどのメソッドにあたるのですか?
>>678 区別する方法は知らない。
> 何で
区別する必要がないから、じゃない?
>>681 あ、やっぱ出来ないのね。つーか、何で区別する必要ないの?
notify()されたかタイムアウトしたかって完全に意味違うぞ。
pthread_cond_timedwait()はタイムアウトしたらETIMEDOUT返す。
WaitForSingleObject()もWAIT_TIMEOUT返す。
普通はこんなもんだと思うんだが。
やっぱJavaって変な仕様多いな・・・(^^;
そりゃ変だよ。最初はthread.stop()なんていう糞仕様があったぐらいだし。 複数オブジェクトに対しor条件でwaitできれば少しはマシだったのに。 ああでも最近のJavaがどうなってるかは知らないよ。 1.4なんてぜんぜん見てない。 > 完全に意味違うぞ。 意味は違うけど、その後の処理は *ほとんどの場合においてほとんど同じ* という罠。 solarisのman pageのcond_timedwait()の使用例でも、抜けた後、 「やっぱり処理する必要があるかチェック」してたりする。 俺のトリアタマでは、複数のワーカースレッドが単一のリクエストキューを 待つ、という使い道しか思いつかないや。
684 :
名無しさん@XEmacs :02/10/14 18:53
pthread_cond_timedwait()がtimeoutを決めてから、 pthread_cond_signal()が発行された時、 timedwait()を行った側でsignal状態の後始末をする必要があるかどうか? ある: 返り値で区別出来てもraceは残る。→何らかの方法で解決。 ない: しかしどちらかは知る必要はある: 返り値で教えろや、(゚Д゚)ゴルァ! どちらでもいい: (´-`).。oO(返り値何のためにあるのだろう) 最初の場合は、排他しながら調べるしかないね…
>>683 確かに普通の場合はほとんど同じことが多いかもしれない。
ちょっとWin32のEventみたいなの作ってて、wait()系のメソッドを
包んだ待機メソッド(タイムアウト付きも)実装するのに不便だな、と。
686 :
デフォルトの名無しさん :02/10/15 00:00
セマフォをOSでなくソフトで実現する方法ってありますか?
>>686 メッセージとか共有メモリを使って
代替の機能は作れると思うけど。
意味は、ないわな。
688 :
デフォルトは上限無しさん :02/10/15 14:40
>>686 セマフォは本来ソフトウェアだけで実装できるものだが、
タスク切り替えをしなければいけない/した方が効率がいい都合上、
カーネルスレッドなシステムではカーネルに実装されていること多い。
自分で実装する場合、タスク切り替えをどうするか考えないといけない。
M:Nスレッドが実装されているシステムだと、CPUを明け渡すAPIがあると思う。
Linux, *BSD, Solaris, NGPTのソースが参考になる。
UNIX System V IPCのセマフォのように、
processが死んだ時のundoを実装しているような高機能なものを作ろうとすると、
やはりカーネルの世話にならざるを得ない。
690 :
デフォルトの名無しさん :02/10/22 04:26
Redhat8, gcc-3.2, glibc-2.2.93 でコード書いているんですが、acceptが妙な 戻りで帰ったとおもったら直後、突然SIGKILLされてしまいます。 [pid 8618] <... accept resumed> 0x4185fa6c, [0]) = ? ERESTARTSYS (To be restarted) [pid 8617] <... select resumed> ) = ? ERESTARTNOHAND (To be restarted) [pid 8618] +++ killed by SIGKILL +++ +++ killed by SIGKILL +++ これの原因、何かわかりませんか・・? tcpのポートをbindしてacceptしている だけなんですが。。
691 :
デフォルトは上限無しさん :02/10/22 16:29
>>690 > 妙な戻り
signalによるsystem callの中断って分かりますか?
/usr/include/linux/sched.hのマクロなんかでは積極的に使ってますね。
pid 8617の方は、signalによるsystem callの中断があり、
system callをrestartしようとしたら、
指定されていたfile handleがなくなっていた、というエラーです。
glibcはpopen(3)以外ではSIGKILLを出さないみたいだけど…
状況がよく分からないので、こんなところですね。
WIN32ですが、クラス内でスレッド作るってどうやるんでしょう?
>>692 クラスの中で_beginthreadしてください
としか言えない
Javaみたいにクラスまるまるスレッド化とかは無理よ?
>>693 startメソッド呼んだらrunメソッドが新しいスレッドで
走るクラスくらい簡単に作れると思うけど
446 名前:デフォルトの名無しさん 投稿日:02/10/24 11:12 //以下では駄目なのですがどのようにすれば良いのでしょうか? //ThreadReceptionはクラス内で定義したいのですが・・ class ThreadClass { public: void ThreadHead(); void ThreadReception(void*); private: }; void ThreadClass ::ThreadHead (){ _beginthread(ThreadReception,0,0); return; } void ThreadClass ::ThreadReception(void*){ return; }
あ、名前欄戻し忘れた
ごめん_beginthreadでもできた。 コンパイルして確認とってないから間違ってるかもしれないけど そのへんは適宜脳内補完してくれ class ThreadClass { public: void ThreadHead(); void ThreadReception(void); private: static void ThreadClass::RealThreadReception(void* tc); }; void ThreadClass ::ThreadHead (){ _beginthread(RealThreadReception,0,(void *)this); return; } void ThreadClass ::ThreadReception(void){ return; } static void ThreadClass::RealThreadReception(void* tc){ return ((ThreadClass *)tc)->ThreadReception(); }
度々すいません・・。 '_beginthread' : 1 番目の引数を 'void (void *)' から 'void (__cdecl *)(void *)' に変換できません っていわれるんですが・・。
>>699 いわれたまんまだろ
そのぐらい自分でどうにかしろ
すいません、勘違いでした。 無事コンパイル通りました、ありがとうございました。m(__)m
702 :
デフォルトの名無しさん :02/10/26 21:58
Cの通信アプリで、 printfを削除すると挙動が変わってしまうのですが、 そんなときどうすればよいのでしょうか?
>>702 挙動が変わる原因がタイミングによるものでないなら、原因は 99% 以上君のプログラムのミスだから、ソースコードレビューを死ぬほどやりなさい。
704 :
デフォルトの名無しさん :02/10/26 23:08
printf入れると、スレッドのプライオリティが下がる ような挙動なんです。
はぁ?
706 :
デフォルトの名無しさん :02/10/26 23:29
WaitForSingleObjectに渡すハンドルをもとに、 別スレッドからこのスレッドを破棄したいのですが、 可能でしょうか?
>706 Win32の話ね。 WaitForSingleObjectに渡すハンドルってスレッドハンドルのことなら TerminateThreadに渡せばスレッド終了できるけど…。 独自プロトコル作ってイベントやメッセージで通信するのがお勧めだよ。
>>704 >>705 じゃないけど、確かに「ハァ ?」だよ。
単に、「スレッドのプライオリティが下がるような挙動」じゃわけわからんよ。
具体的に何がどうなるのか書いてみ。
709 :
デフォルトの名無しさん :02/10/27 00:54
アーカイブってどういう意味? 馬鹿ですいません 教えてくださひ
710 :
デフォルトの名無しさん :02/10/27 00:55
>>707 ありがd。
私の考え方がマズかったです。
SetEventを使用した独自プロトコルでうまくいきました。
713 :
デフォルトの名無しさん :02/10/27 01:01
>711 サンキュ >712 すまん
クラス内にスレッドを作成して、そのクラスを配列で複数定義して 処理を同時進行でするようなプログラムを作ったんですが、途中で処理速度が著しく落ちます。 クラスにしなかった場合とした場合とを比べるとクラスにしない場合の方が10倍ぐらい早いです。 何度もデバックしてみましたが原因不明です。 エラーもでないしなにがわるいんだろうか・・・・・
複数のスレッドが激しくCPUを奪い合うようになってたら、 シングルスレッドよりも遅くなるよ。
クラス化した理由はスレッドの関数を複数定義するのが面倒だし、スマートじゃない為でして、 #クラス化しなくてもいい方法があるかもしれませんが・・ スレッドの数はクラス化する前も、した後も同じなので恐らく速度が落ちる事は無いと思うんですが・・
そりゃアンタのプログラムがバグってるか アンタがバグってるかのどっちかじゃろうね
718 :
デフォルトの名無しさん :02/10/29 21:22
子スレッド中でのfork-execは、安全ですか? ターゲットはLinuxおよびCygwinです。
pthreadsでは、fork直後のexecは安全であるべきと いうことになっていたので逝ってきます。
720 :
デフォルトの名無しさん :02/10/30 00:51
Cygwinでpthreadはもうまともに動いているの? 少し前に聞いた話だと、バグだらけで使い物にならないとか。
>>720 バグ取りは随時やってるようだけど、「まともに動いている」という話は
最近でも聞かないねぇ。まぁ動けばめっけもん、くらいに考えておいた
方がいいんじゃないかな。
722 :
デフォルトの名無しさん :02/10/30 20:00
cygwinのpthreadならwindowsのAPIラップするだけじゃないの? 自体はそんなに簡単じゃないのかな?
UNIXエミュレーションとの整合を取る部分で死ねるのだと思われ
724 :
デフォルトは上限無しさん :02/10/31 00:01
>>722 そんなに簡単じゃない。
pthreadはpthread単独で意味があるわけでなく、
signal, I/Oなどなどとセットではじめて意味がある。
それぞれとの相互作用においてPOSIXに合っていなければ、
わざわざ使う意味がない。(Win32 APIでいいじゃんという意味において)
「APIラップするだけじゃないの」と疑問を抱くレベルなら 確かにAPI直接使えばよさげだ
Cランタイムとの整合性なんかを考慮してねえとまずくないかな
そらまずいだろうね。 ただまぁ最悪自分で同期取ればいい話でもあるが。
APIで上げたスレッドからは一切Cygwinの機能を使わなければ なんとかなりそうだ
729 :
デフォルトの名無しさん :02/10/31 17:33
pthread仕事で使ってる人います?
使うかもしれないから調査中
Cygwinのsocketは、未だthread safeではなさげ(DLLのソース読んで確認) ひとつのfdに対して複数スレッドでaccept(2)して、ひどいめに遭った
cygwinってfork使えますか?
fork遅いよ っていうかスレ違いだろ
cygwinってspoon使えますか?
736 :
デフォルトの名無しさん :02/11/12 19:32
Windowsであるクラスに参照カウントを持たせ、InterlockedIncrement./InterlockedDecrementで マルチスレッド対応にしようとしたのだが… void ref() { InterlockedIncrement(&m_ref); } void release() { if (InterlockedDecrement(&m_ref) == 0) { delete this; } } ところが、delete thisの直後にref()が呼ばれると、m_ref自体が解放された領域にあるため、 とんでもない値になってしまう。参照カウントをメンバー変数にするのが間違い? どうしたらいんだろう?マルチスレッドのエキスパート様の降臨おながいします
> delete thisの直後にref()が呼ばれる delete thisされたってことは、そのオブジェクトはもう参照されていない と判断されたんだがら、その後にrefが呼ばれること自体がおかしい。
参照カウントを0から始めたに100スレッド
ある時点で、m_ref>0だったとします。 2つのスレッドが、それぞれ同時にref()とrelease()を呼び出すと…
ref() と release() が互いに排他してなきゃ動くわけないじゃん。
void ref() { EnterCriticalSection(&m_cs); InterlockedIncrement(&m_ref); LeaveCriticalSection(&m_cs); } void release() { EnterCriticalSection(&m_cs); if (InterlockedDecrement(&m_ref) == 0) { delete this; } LeaveCriticalSection(&m_cs); } としても、ref()でInterlockedIncrement()にたどり着いたときには…
あるオブジェクトに触れるスレッドが一つふえたら そのオブジェクトの参照カウントをageておく必要があることに 気づいてないに1000はらたいら
>739 それもなんだかおかしな動作だな。 refを発行する、というのは、どっかからobjectを貰ってきてるわけだろ。 で、releaseを発行するということは、所有権の一端を持っているわけだよな。 それで、deleteが実行されるというのは、 「refcount == 0かもしれないobjectが渡ってきた」 「release発行しすぎ」 ってなわけだろ。refするタイミングとか、考え直した方がいいんでないか?
refが参照カウントを増やす(objectを貰って来る)ためのものなのだが…
736はひょっとしてCOMを知らない?
いやCOMじゃなくて。 あるオブジェクトのインスタンスが作られるとm_ref=1となっていて、 そのオブジェクトを例えば別のスレッドが使うためにコピーを作るとm_ref=2 となる。 まさにその瞬間に、インスタンスの元のホルダーがオブジェクトを破棄しようとすると、 m_refのインクリメントとデクリメントが同時に起きる。 Interlocked...は同時じゃないが、ref()とrelease()が同時に呼ばれrelease()を 実行しているスレッドの方が早くCriticalSectionを獲得して解放したのち、 InterlockedIncrementが呼ばれると、解放されてしまうので値が不定になってしまう。
「別のスレッドが使うためにコピーを作る」ときに 「インスタンスの元のホルダーがオブジェクトを破棄」しちゃおかしいだろ。 「別スレッドに渡す」ときにコピーができるもんだろ、ふつー。
>>746 Deleteされてしまうことがあるobject自身に、
objectの管理を「全て」任せようということ自体が無理。
Handler patternで行くか、refererにべたにcodeを書いてしまう。
つーかな。それはrefcountの問題と違うねん。たとえば、 method1() {delete str; str=0; } method2() {func( *str );} このメソッド2つが同時実行されるようなのとおなじ問題なわけよ。 あえて解決策を示すなら、 method1() {lock(); delete str; str = 0; unlcok(); } method2() {lock() if( str ) func(str) unlock(); } とかしないといけない。
ひょっとしてrefcountをさらにポインタや参照で管理しようとしてないか? そんなのrefcountの意味が全くないぞ。根本的にrefcountについて誤解してるだろ。
>>750 俺もそんな気がして来た。グローバルなオブジェクトや静的なオブジェクトを
参照カウントでやろうとしてるような気もするし。
>746 やっぱり、そういう事になりますか。 >749 それは、ちっとも解決にならない。 method2がこの場合ref()なわけで、ref()から戻ったら、そのオブジェクト使おうと するんだから。 >750 参照カウントは、扱われるインスタンス内に有りますが、 そのインスタンスを指すスマートポインターのようなクラスで持たなきゃならないって 事ですか? そうでなくて、インスタンスと別にアロケートして参照カウント作ってもだめって事だけ? >グローバルなオブジェクトや静的なオブジェクトを参照カウントでやろうとしてるような気もするし。 流石に、そんなこたぁない。
分からんヤツやな、、、 refする前にreleaseが発行されてrefcount==0になる 可能性があるなら、refする前に、oobjectが生きてて、 refできるか確かめないかんやろ。その結果、objectが 死んでるなら、refしてobject渡すのは諦めなアカン。 で、そこでobjectが死んでるのが間違いなら、releaseか refの発行の仕方がオカシイんや。
>>752 > >746
> やっぱり、そういう事になりますか。
ジサクジエーン?
>>752 > 参照カウントは、扱われるインスタンス内に有りますが、
> そのインスタンスを指すスマートポインターのようなクラスで持たなきゃならないって
> 事ですか?
> そうでなくて、インスタンスと別にアロケートして参照カウント作ってもだめって事だけ?
場所は関係ない。ただし、インスタンスとカウンタの対応を管理することを考
えれば、インスタンス内に置くか「スマートポインターのようなクラス」って
のが確実で手軽だし常套手段。
参照が増減するたびに必ずカウンタも同期しなきゃ行けないってこと、わかっ
てる? これは本来アトミックな処理なので、別スレッドに渡すってのも参照を
増やすことになるんだけど、それとカウンタの更新を別スレッドに分けちゃい
けない。
単一スレッド内でコピーする場合は複製によるカウント処理が終るより前にオ
リジナルが解放することはないので保護されるけれど、別スレッドにしてしまっ
たらその順序が保証されなくなってしまう。
>>754 多分 748 宛てだと思われ。
レス番号と間違えてコメント先頭のポインタを書いてしまう間違いは漏れも時々
やってしまう。
なんか昨日から粘着が居るが >753 >分からんヤツやな、、、 あんたほどでは(W >refする前に、oobjectが生きてて、refできるか確かめないかんやろ。 確かめた時生きてても、じゃあ参照しようとしたら死んでる罠 確かめるときに参照かうんと増やす何て言うなよ(W >755 >参照が増減するたびに必ずカウンタも同期しなきゃ行けないってこと、わかってる? それは当然ですね。 >これは本来アトミックな処理なので、別スレッドに渡すってのも 別のスレッドに渡すのではなく、 あるスレッドAが参照カウントを持つOのインスタンスをつくって、 別のスレッドBがそのオブジェクトをもらおうとしたらば、 Aはもう要らないとOを破棄しようとしている最中だったわけです。
>>753 736 にはもう何も言わなくていいよ。
十分答え出てるのに見ようとしないんだから。
>>757 > 別のスレッドに渡すのではなく、
「渡す」つってんのはインスタンス自体じゃなくて参照のことをいってんだけど。
ポインタといったほうがいい?
> あるスレッドAが参照カウントを持つOのインスタンスをつくって、
> 別のスレッドBがそのオブジェクトをもらおうとしたらば、
この「もらおうとした」ってどういう状態を考えてるわけよ。
スレッドBはOのインスタンスo1に対する参照を受け取ってないわけ?
もし受け取ってるんならその時点でカウントしないとだめぽ。
>「渡す」つってんのはインスタンス自体じゃなくて参照のことをいってんだけど。 >ポインタといったほうがいい? 「渡す」というのは、あるスレッドAがインスタンスOの参照(カウントが増えた状態)を、別のスレッドB がアクセスできるようにするという意味で使いました。 そうではなくて、スレッドAの預かり知らぬところで、スレッドBがインスタンスOを コピー(の過程で参照化運とは増える)して使おうとするということです。 参照を受け取った時には、当然参照カウントは増えていますが、Oの参照カウントを (クリティカルセクション獲得後)増やそうとしたら、スレッドAが解放してしまっていた わけです。 >758 そういうなら、参照カウント使ったクラスうpしてみそ。逃げますか?(W
>>760 逃げる。
そしておまいは困る。ザマーミロ。
>確かめた時生きてても、じゃあ参照しようとしたら死んでる罠 もう一度だけ言うぞ。 「確かめる」と「ref()呼ぶを」、一つのLock内でやれ。 もちろん、releaseの呼び出しにも、おなじLockをかけろ。 それでも、refcountが0になるなら、releaseを呼びすぎているだけ。
そんなに広い範囲でロックかけないで済む方法ってないの?
話してる前提が違うんじゃない? >method1() {lock(); delete str; str = 0; unlcok(); } が method1() {lock(); delete this; /*this = 0;XXX*/ unlcok(); } だから、method2()のifがそもそも出来ないという話
lock() str->release(); str = NULL; unlock();
>763 762のlockはそんなに広くないはずだが。
>>736 参照カウントが 1 のオブジェクトを複数のスレッドから参照してる時点で、
ref を呼び忘れてる。
参照回数0 のオブジェクトに到達することが正しい振る舞いだとしたら、
それは通常の参照じゃなく、弱い参照だ。
>>736 そもそも、スレッドが生きているかどうか分からないオブジェクトへの
ポインタを受け取ること自体に問題があるような。まさか、
スレッドA:
p = new クラス();
Bに渡す(p);
p->release();
スレッドB:
p = Aから受け取る();
p->ref();
というコードを書いていないだろうな?もしそうなら構造上の問題。
Bから見える場所にpを格納したなら、その分の参照カウントを数えなくては
ならない。それって本質的にはシングルスレッドでも同じことだけど。
> あるスレッドAが参照カウントを持つOのインスタンスをつくって、 COM知ってさえいれば・・・
つか、スレッドBに渡されたことをどうやってAは知るんだ?
>>770 普通Aがそれを知る必要は無いと思うが?
単にBが自分でディクリメントすればいいだけで。
なんか皆さん盛り上がってますが…
>>745 >>769 に同意。
リファレンスカウントのサンプルを見たければCOMを勉強すればよい。
それと。日本語で一所懸命書かれてもどうにも伝わりにくいようですな。
C言語で(擬似コードでも可)書いた方が意図が伝わると思いますが。
>>760 > 参照を受け取った時には、当然参照カウントは増えていますが、Oの参照カウントを
> (クリティカルセクション獲得後)増やそうとしたら、スレッドAが解放してしまっていた
> わけです。
そりゃカウントミスってる。AがOを持ってるところでBがOの参照を受け取って
カウントも増やしたんなら、カウントは2以上のはずだ。その状態でAが解放し
てしまうというのはバグ。
おまえらスレッド立てすぎです。
>>776 、禿同
マルチスレッド掲示板はやればやるほど
スレッドをsageる方向で書込みしたくなるという面白い側面がありますね。
この間ようやくプ逝1も sage を覚えたようですが
VC++の_beginthreadでプログラムを書いてるのですが 親スレッドから子スレッド(以後スレ)を10本同時進行で走らせていて、すべての処理が終った時 子スレの呼び出しの前に変数でフラグを立てておき、そのスレの最後でフラグをONにし、 親スレでそれを確認してからスレを終わるように処理を書いているのですが、 親スレで子スレのフラグを確認している最中に子スレが書き込みすると処理が停止してしまいます。 (デバックしてみるとその付近で停止したりしなかったりする) このスレのどこかで参照は同時に行ってもかまわないようなレスをみたのですが(記憶が確かなら…) 同時書きこみでない場合(書き込み中を参照)でもだめなのでしょうか? クリティカルセッション等やらねばダメなのでしょうか? それともこのような設計が悪いのでしょうか・・
>>776 >マルチスレッドプログラミングは、やればやるほど
>スレッドを減らす方向に設計したくなるという面白い側面がありますね
私もスレッドにはうんざりですw
まぁ設計が悪いんでしょうが・・・
>>779 DQNは使うな
つーか、一冊でも参考書読め
よーくデバックすると原因が見つかりました。。^^; 長文書いたにもかかわらずすいません・・ 後余談ですが、デバック中に子スレッドでconnect、closesocketを何度かやっていると ある一定回数(かなりの回数)を超えた時、connectが出来ない状態になりました。 何らかのエラーが発生した場合そのエラーを表示するようにプログラムを 書いているのですが全く表示されません。 Socketの処理は居たってシンプルなもので、スレッドとは別で行っているのでバグは無いと思うのですが・・。 このような事は通常起こり得るのでしょうか?
どうして、参照カウントが増えた後の話にしたがるのか…
784 :
デフォルトの名無しさん :02/11/14 11:07
>765 >766 参照カウントを持つオブジェクトのリストがあって、追加・削除、参照(+そのための検索) を行おうとすると、それぞれでリスト全部ロックしないと… まあ、注目してるノードとその前後だけロックというのも有りうるけど面倒すぎる。 リスト自体が要素すうもってるし。 >767 参照できるようにする過程での話です。 参照カウントインクリメント不足は、お腹一杯。 >768 スレッドBのAから受け取る()は、どういう処理? そのなかで、当然Mutexとかで排他制御して参照カウント増やすんでしょ? その瞬間の話。 >769 実はCOMです。 COMのモジュール内で持ってる情報の管理でつまずいてる。 769はSTAだけつかってなさい。
785 :
デフォルトの名無しさん :02/11/14 11:11
>772
ちみもSTAだけつかってなさい。
> C言語で(擬似コードでも可)書いた方が意図が伝わると思いますが。
そいでは、>774の
Reference Counting - Part III (Multithreading!)
http://www.gotw.ca/gotw/045.htm から
String::~String() {
bool bDelete = false;
data_->cs.Lock(); //---------------------------
if( data_->refs == Unshareable || --data_->refs < 1 )
bDelete = true;
data_->cs.Unlock(); //-------------------------
if( bDelete)
delete data_;
}
String::String( const String& other ) {
bool bSharedIt = false;
other.data_->cs.Lock(); //---------------------
if( other.data_->refs != Unshareable ) {
bSharedIt = true;
data_ = other.data_;
++data_->refs;
}
other.data_->cs.Unlock(); //-------------------
if( !bSharedIt )
data_ = new StringBuf( *other.data_ );
}
(つづく)
786 :
736=784=785 :02/11/14 11:23
Sharable/Unsharableは置いといて、 Thread A Thread B delete O1呼び出し O2 = O1 (otherがO1) data_->cs.Lock(); other.data_->cs.Lock() if (--data_->refs < 1) bDelete = true; data_->cs.Unlock(); if (bDelete) data = other.data; delte data; ++data_->refs; other.data_cs.Unlock() 例のコードではStringなので、ロック後解放済みだったら空の文字列 を返せばよいのですが、実際には目的のデータであることを確認後 Thread BはO1のコピーのO2を手に入れようとしているので困ってます。 目的のデータがあるかどうかの検索の最初から、コピーを手に入れるまで と解放処理を呼び出すのもまるっきり排他制御すればできるのは明らかで すが、極端にパフォーマンスが落ちてしまいます。
>>773 > そりゃカウントミスってる。AがOを持ってるところでBがOの参照を受け取って
> カウントも増やしたんなら、カウントは2以上のはずだ。その状態でAが解放し
> てしまうというのはバグ。
はぁー。
受け取る処理ってどうやるのさ?
>774
これからよく読んでみます。
ありがと。
>>786 > Thread A Thread B
ここでBは既にO1への参照を持ってんだろ?
> delete O1呼び出し O2 = O1 (otherがO1)
O1は、スレッド間で共有しているリスト中の要素としてある。 O2=O1は、そのリストから目的の物を検索して取り出す処理の中。
マルチスレッドのプログラムで 素朴リファレンスカウントGCをやるなら、 すさまじい細粒度ロックで効率が低下するのは 覚悟しなきゃ。 (普通のGCを使ったほうがずっと速いよ。)
>>789 やっぱりおかしいな。リストがStringを持ってるわけだろ?
それで、Thread Aがリストから要素を削除したら~String()が呼ばれる
わけだが、その前にThread Bがリストの要素への参照を持ってるなら
参照カウントは2になってなきゃおかしい。
こういうことするなら、当然文字列を指す可能性のあるオブジェクト
全部にリファレンスカウント付けて管理してるんだろ?
そうか。Stringというより GarbageCollectedというスマートポインタを作って、 ヒープのオブジェクト全部GarbageCollectedを継承するように するんだな。 そして、リストの検索とかやるときは、1つ1つの要素を ロック・ref++・アンロック、ロック・ref--・アンロックすると。
>>789 もしかして
「排他制御せずにリストにアクセスしたら、変になるんですけど。」
って言ってる?
スレッドAがリスト中のO1を削除するには、
list.remove(index)
あるいは
list.remove(O1)
スレッドBがO1のコピーを作るには、
O2 = list.get(index)
だよな?
で、この get と remove はロックを使わずやりたいと。
そういうことか?
>791 >その前にThread Bがリストの要素への参照を持ってるなら >参照カウントは2になってなきゃおかしい。 リストの要素への参照とは? O1がそれだと言っているのか(W >793 >で、この get と remove はロックを使わずやりたいと。 >そういうことか? そう。 でも、 >「排他制御せずにリストにアクセスしたら、変になるんですけど。」 という事じゃない。 removeで要素中のO1は削除されるけど、Thread BがO2を手に入れていれば O1-+ +-->ref:2,data:"ABC" O2-+ から O2---->ref:1,data:"ABC" となり、他のスレッドは、もはやこのデータにアクセスできないが、 Thread BはO2から使える。O2が不要になって破棄したら、データ本体も解放される。
リスト操作たるgetとremoveにlockかけんかったら、 そいつらが平行したらあぼーんちゃうの。 まあ、「いや、実は〜」とかいって 新状況が出てくるのかも知らんけど(ワラ
>>755 で
> 参照が増減するたびに必ずカウンタも同期しなきゃ行けないってこと、わかっ
> てる? これは本来アトミックな処理なので、
と書いてある意味分かんないのか?
>>789 > O2=O1は、そのリストから目的の物を検索して取り出す処理の中。
てんなら、その処理中での参照の追加とカウントの増加は原理的に(そのオブ
ジェクトに対する)排他処理は必須ってことなんだが。
797 :
デフォルトの名無しさん :02/11/14 15:42
「getしてO1の参照先のref countが増える」までが アトミックに行われないとまずいね。 getが返すべきO1を得た後で、かつO1のrefが増える前にrefがゼロに なっちゃう。 やはり、 ・リスト全体にmultiple-readers-single-writer lockをかける。 ・リストの要素1つ1つに排他的ロックをかける。 のどちらかが必須。
798 :
デフォルトの名無しさん :02/11/14 15:50
>>796 禿同
getの中で「注目してるオブジェクト」を示すポインタが
あれば、そいつの参照も数えるべき。
あるオブジェクトを指す変数がある瞬間に3つあるなら
(たとえば「リストから」「Thread Aの局所変数から」
「Thread Bの局所変数から」)、参照カウントはその瞬間
3でないと間違い。
>>784 (=783?)
>実はCOMです。
>COMのモジュール内で持ってる情報の管理でつまずいてる。
COM扱っててこの有様は信じられない。
>796 未だに問題のポイントがわかってない言語障害者が居ますね。 >797 やっぱり、そうなっちゃいますかね。 >799 COMは関係なかろう、STAならInterlock何かする必要無いし、 そうでなければ、COMでも同じ。
ふつーのGC使えば、誤爆開放しちゃうdangling pointer問題からは 逃れられる。 でも、2人が同時にリストにあぷデートに行ったらどうやっても ロック必須だけどナー
なんか禿しく釣られまくったような気がしてきた…。
ところでReadWriteLockでスタベーションフリーでLockのUpgrade/Downgradeも できるようなの誰か知らんか?
>>736 考え方おかしいよ。
管理する側とされる側がごっちゃになってる。
そもそもdelete後に破棄されたインスタンスの排他制御
オブジェクトを参照しようとしてる事をおかしいと思わないの?
805 :
デフォルトの名無しさん :02/11/14 22:28
便乗で質問です。 スレッド間で、GC(インクリメンタルなマーク&スイープ)で管理された 共有領域のメモリオブジェクトを使いたいんですが、メモリオブジェクト にはアクセスする度に排他制御しないといけませんよね? 参照するだけなら不要なのはわかるんですが、ポインタを繋ぎ変えたりも したいので、結局双方でロックしてないと駄目ですよね。 素直に組むと、メモリオブジェクトの粒度が小さいので排他制御にかなり の時間が割かれてしまいそうなんですが、良い方法はないでしょうか。 素人考えで思いついたのは、スレッド毎にローカルなメモリオブジェクト 領域を使って、処理が完了したら、その結果を共有メモリオブジェクト 領域に移すという方法で、排他制御は共有メモリにアクセスするとき のみ掛けるというものですが、この方法だとスレッド毎にGCが必要な気が します。 もっと一般的な方法があったらお願いします。
>>805 読むだけなら排他制御は不要だよ。
整数や文字を書き込むときも(共有変数以外は)不要。
ポインタを書いたときはライトバリアでGCに通知。
これも別に排他制御はいらない。たとえばスレッドごとにキューを作って、
ページ単位とかでまとめて渡せばよい。
>>806 ありがとうございます。
ライトバリアでマークする経路を保証するって事ですよね。
共有領域とローカルの区別をする手段が思いつかない(複数
ブロックにまたがってる)んで、改竄個所を全部保護する様に
書き直さないとまずいのかな。
ちょっと考えてみます。
ヒープに置くポインタはすべて template Pointer<class T> ... みたいなオブジェクトにして、コピーコンストラクタ でライトバリアをかければよいんじゃないだろうか。
>804 頭おかしいよ。 こんなのどこにでもある。見たこと無いのか?
>>736 何人もの人間が否定してるんだから、おかしいのはお前だろ(笑
じゃあ、COMもおかしいのか?
>>809 「どこにでもある」 が 「おかしくない」 の理由には全然ならない事に気付け。
つーか、そんなのそうそう転がってないはずなんだが、あんたよっぽどクソな
サンプルに見舞われてるんだな。
>>811 おかしいのは COM を把握してないのにわかったつもりになってるあんたの頭。
つーか、教えを乞う立場だったら、もっと謙虚になれ。
主観を捨てろ。
答えへのポインタはもう不必要なほど出ているのに、あんたはそれを全部捨てている。
>812 >つーか、教えを乞う立場だったら、もっと謙虚になれ。 共有しているオブジェクトの集合に丸ごとロックかけずに、 各オブジェクトの参照カウントだけで済むかがポイントなのに、 参照カウントのインクリメント不足だとか、 COMを知ってればとか、 おんなじ事 おんなじ事 おんなじ事 おんなじ事 ばかーーーり。 しつこつ しつこく しつこーーーーく 同じこと繰り返す粘着が多くてウンザリ。 getはアトミックだとか…あのなあ、それ自体はアトミックでもremoveとgetを同時に呼ぶことは出来るんだよ。 参照を持っているならとか…あのなあ、その参照を受け取るのがgetだろ。共有オブジェクトのgetなんだよヴォケ。 じゃあ、参照を手に入れる処理を書いてみろというと、とたんに逃げ出す。 どうしてポイントがずれた香ばしい奴が多いのか。
>812 >「どこにでもある」 が 「おかしくない」 の理由には全然ならない事に気付け。 >つーか、そんなのそうそう転がってないはずなんだが、あんたよっぽどクソな >サンプルに見舞われてるんだな。 これ見たこと無いか? static ULONG WINAPI Increment(LPLONG p) {return InterlockedIncrement(p);} static ULONG WINAPI Decrement(LPLONG p) {return InterlockedDecrement(p);} ULONG InternalAddRef() { return _ThreadModel::Increment(&m_dwRef); } ULONG InternalRelease() { return _ThreadModel::Decrement(&m_dwRef); } STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} STDMETHOD_(ULONG, Release)() { ULONG l = InternalRelease(); if (l == 0) delete this; return l; } まあ、君のコードの中では、 static ULONG WINAPI Increment(LPLONG p) {return ++(*p);} static ULONG WINAPI Decrement(LPLONG p) {return --(*p);} しか使われないと思うが(W
736の、これまでの発言で推測できること。 1.listでCOM objectを束ねているらしい 2.list内のあるCOM objectに対して、 releaseとrefが(release->refの順で)発生して死ぬようだ 3.list全体に対するlockはかけたくないらしい (listが持つCOM objectに対する個々のロックは可能みたい?) 736の発言だけで、この問題がわかるかってーの。 それを736の時点で言えば、まだ混乱は少なかっただろうに。 変に情報を出し惜しむから、おなじ事をしつこく何度も 言われる羽目になる。おまけに自分のことを棚に上げて しつこいとか、ポイントがずれてるとか、香ばしいとか言うし。
それで?
で、815であげた推測は正しいのかい? というか、コードだせ、コード。問題の起こる、 必要最小限の、736の書いたコードを。
738 :デフォルトの名無しさん :02/11/12 20:25 参照カウントを0から始めたに100スレッド 740 :デフォルトの名無しさん :02/11/12 21:24 ref() と release() が互いに排他してなきゃ動くわけないじゃん。 742 :デフォルトの名無しさん :02/11/12 21:57 あるオブジェクトに触れるスレッドが一つふえたら そのオブジェクトの参照カウントをageておく必要があることに 気づいてないに1000はらたいら 743 :デフォルトの名無しさん :02/11/12 21:58 >739 それもなんだかおかしな動作だな。 refを発行する、というのは、どっかからobjectを貰ってきてるわけだろ。 で、releaseを発行するということは、所有権の一端を持っているわけだよな。 それで、deleteが実行されるというのは、 「refcount == 0かもしれないobjectが渡ってきた」 「release発行しすぎ」 ってなわけだろ。refするタイミングとか、考え直した方がいいんでないか? 745 :デフォルトの名無しさん :02/11/12 22:52 736はひょっとしてCOMを知らない? 747 :デフォルトの名無しさん :02/11/13 10:35 「別のスレッドが使うためにコピーを作る」ときに 「インスタンスの元のホルダーがオブジェクトを破棄」しちゃおかしいだろ。 「別スレッドに渡す」ときにコピーができるもんだろ、ふつー。
750 :デフォルトの名無しさん :02/11/13 11:21
ひょっとしてrefcountをさらにポインタや参照で管理しようとしてないか?
そんなのrefcountの意味が全くないぞ。根本的にrefcountについて誤解してるだろ。
751 :デフォルトの名無しさん :02/11/13 11:28
>>750 俺もそんな気がして来た。グローバルなオブジェクトや静的なオブジェクトを
参照カウントでやろうとしてるような気もするし。
753 :デフォルトの名無しさん :02/11/13 15:40
分からんヤツやな、、、
refする前にreleaseが発行されてrefcount==0になる
可能性があるなら、refする前に、oobjectが生きてて、
refできるか確かめないかんやろ。その結果、objectが
死んでるなら、refしてobject渡すのは諦めなアカン。
で、そこでobjectが死んでるのが間違いなら、releaseか
refの発行の仕方がオカシイんや。
767 :デフォルトの名無しさん :02/11/13 21:20
>>736 参照カウントが 1 のオブジェクトを複数のスレッドから参照してる時点で、
ref を呼び忘れてる。
参照回数0 のオブジェクトに到達することが正しい振る舞いだとしたら、
それは通常の参照じゃなく、弱い参照だ。
769 :デフォルトの名無しさん :02/11/13 23:23
> あるスレッドAが参照カウントを持つOのインスタンスをつくって、
COM知ってさえいれば・・・
772 :デフォルトの名無しさん :02/11/13 23:58
なんか皆さん盛り上がってますが…
>>745 >>769 に同意。
リファレンスカウントのサンプルを見たければCOMを勉強すればよい。
それと。日本語で一所懸命書かれてもどうにも伝わりにくいようですな。
C言語で(擬似コードでも可)書いた方が意図が伝わると思いますが。
773 :デフォルトの名無しさん :02/11/14 00:03
>>760 > 参照を受け取った時には、当然参照カウントは増えていますが、Oの参照カウントを
> (クリティカルセクション獲得後)増やそうとしたら、スレッドAが解放してしまっていた
> わけです。
そりゃカウントミスってる。AがOを持ってるところでBがOの参照を受け取って
カウントも増やしたんなら、カウントは2以上のはずだ。その状態でAが解放し
てしまうというのはバグ。
736 荒らしケテーイ (いや、元々そうだったという説もあるが・・・) という訳で出て逝ってくれ。
君らのしつこさを確認させてやっただけだよ
( ´,_ゝ`)プッ
結局誰も判らんのか。それならそう言えよ無能者ども。
>>822 あのさあ、
しつこいのは お ま え (w
消えろ
>>813 > 共有しているオブジェクトの集合に丸ごとロックかけずに、
> 各オブジェクトの参照カウントだけで済むかがポイントなのに、
参照カウントのインクリメントにはロックは*原理的に*必要不可欠。
してないのはシングルスレッドを前提にしてる場合だけ。
わかった?
> 参照カウントのインクリメント不足だとか、
> COMを知ってればとか、
> おんなじ事 おんなじ事 おんなじ事 おんなじ事 ばかーーーり。
> しつこつ しつこく しつこーーーーく 同じこと繰り返す粘着が多くてウンザリ。
なんでおんなじ事をこんなにしつこく説明してやらなきゃならんのか…。
> getはアトミックだとか…あのなあ、それ自体はアトミックでもremoveとgetを同時に呼ぶことは出来るんだよ。
> 参照を持っているならとか…あのなあ、その参照を受け取るのがgetだろ。共有オブジェクトのgetなんだよヴォケ。
そのアトミックなgetにカウントのインクリメントを含めてないからバグって
んだろが。
まだ言ってるのか。 >参照カウントのインクリメントにはロックは*原理的に*必要不可欠。 >してないのはシングルスレッドを前提にしてる場合だけ。 >わかった? void ref() { EnterCriticalSection(&m_mutex); InterlockedIncrement(&m_ref); LeaveCriticalSection(&m_mutex); } void release() { EnterCriticalSection(&m_mutex); if (InterlockedDecrement(&m_ref) == 0) { delete this; } LeaveCriticalSection(&m_mutex); } としたら満足か?(W
>826 おまえ、InterlockXXってなんのためにあるのか知らんだろ。 知らない奴に限って、無駄なレスを返しやがる。
としたら満足か、って・・・ 一体何の為にここに質問に来たんだ?
736の無能っぷりをさらけ出すスレはここですか?
>>837 >EnterCriticalSection(&m_mutex);
> InterlockedIncrement(&m_ref);
>LeaveCriticalSection(&m_mutex);
クリティカルセクション張ってるんだから、
インターロック不要なんだけど。
>EnterCriticalSection(&m_mutex);
> if (InterlockedDecrement(&m_ref) == 0) {
> delete this;
> }
>LeaveCriticalSection(&m_mutex);
自分で書いてておかしいと思わないのかなあ・・
>>836 あのなあ、
>>参照カウントのインクリメントにはロックは*原理的に*必要不可欠。
>>してないのはシングルスレッドを前提にしてる場合だけ。
>>わかった?
というのは読めないのか。お前は、自然言語にたいする理解力は0だな。
ロックかけなきゃだめだと言ってるやつがいるから、ロックしたまで。
なーんの解決にもならんし、もともと、Interlockしてるから不要なんだがな。
>830 だわ
で?826も逃げたのか。全く都合が悪くなると逃げて…自分の発言に席にもてよ。 どうせ、別人のフリしてまた別の事言い出すんだろうが
ん?deleteまではロックしなきゃダメかな。 まあ、どのみちref()でロック獲得したときに、解放済みというのは避けられんが。
>>827 > としたら満足か?(W
で、バグは直ったのか? 漏れが満足したからってバグが消えるわけじゃないぞ。
void Item::ref() {
InterlockedIncrement(&m_ref);
}
Item* List::get() {
EnterCriticalSection(&m_mutex);
Item* p = ...;
p->ref();
LeaveCriticalSection(&m_mutex);
return p;
}
この例で行くとListのget()とremove()で競合が起きるんだろ?
ならListのほうで排他処理をするのが自明の理。
やっぱり、List::get()でリストの検索処理が丸ごとロックするしかないのか。
(´-`).。oO(100レスかけてようやく染み込んだのか)
それ以外に無いのか聞いてんだが。 ここのいる連中じゃ無理のようだ(W
>812 >「どこにでもある」 が 「おかしくない」 の理由には全然ならない事に気付け。 >つーか、そんなのそうそう転がってないはずなんだが、あんたよっぽどクソな >サンプルに見舞われてるんだな。 812も逃げたようだな。逃げ足の速い連中だ。
>>838 > それ以外に無いのか聞いてんだが。
散々いわれてんのに。
>>762 とか
>>785 とか。
大体間接的に渡すって話自体
>>789 くらいでいきなりだし。
>>839 > 812も逃げたようだな。逃げ足の速い連中だ。
いつまでも君の相手してらんないしね。
漏れもそろそろ出かけなきゃならないんでバイバイ。
841 :
デフォルトの名無しさん :02/11/15 14:27
winでのTerminateThreadと同じような 関数はunixにありますか?
pthreadならpthread_cancel()かな。TerminateThreadと違って必ずしも即座に 終了するわけじゃないけど。
843 :
デフォルトの名無しさん :02/11/15 14:44
教えて下さい。 pthread_cancel()を実行すると 実行されたスレッドの終了はいつになるのですか?
実行してみればわかる
>840
またバカが湧いてきた。
>散々いわれてんのに。
>>762 とか
>>785 とか。
>762は、各オブジェクト毎にロック掛けるって意味ならロックが多量に必要だし、リストにはロック掛けないのか?
リストにロックかけるんだったら、各オブジェクト毎に掛ける必要なし。
君のような厨には理解で菌だろうがな。
>大体間接的に渡すって話自体
>>789 くらいでいきなりだし。
間接的?ハァ?頭大丈夫?
785は俺だ。
たくっ。ろくに読まないでレスするアホウは書くなっつの。
>いつまでも君の相手してらんないしね。
>漏れもそろそろ出かけなきゃならないんでバイバイ。
いや、君みたいなアホウに相手してくれとは言ってないから(W
お呼びでないの(Wつか出てくんなっての
大体、レスして何か言われたら自分が誰かわかるように名前に番号入れるもんだろ。
言いっぱなしで自己満足してる厨が多すぎ。
740 :デフォルトの名無しさん :02/11/12 21:24
ref() と release() が互いに排他してなきゃ動くわけないじゃん。
826 :デフォルトの名無しさん :02/11/15 13:03
>>813 > 共有しているオブジェクトの集合に丸ごとロックかけずに、
> 各オブジェクトの参照カウントだけで済むかがポイントなのに、
参照カウントのインクリメントにはロックは*原理的に*必要不可欠。
してないのはシングルスレッドを前提にしてる場合だけ。
わかった?
こういう連中は、
void ref() {
EnterCriticalSection(&m_cs);
++m_ref;
LeaveCriticalSection(&m_cs);
}
void release() {
EnterCriticalSection(&m_cs);
if (--m_ref) == 0) {
delete this;
}
LeaveCriticalSection(&m_cs);
}
って書いてるのかな。馬鹿だなー。
こんな事言ってる奴が多いのは オ ド ロ キ。
もはや都市伝説だな。
おっ! 830が、慌ててネットで調べ始めた。まあ、自分の馬鹿さ加減を思い知れ。
おっ! 他にもInterlockだけじゃダメだと思ってる奴も多いな。 まあ、release()のLeaveCriticalSectionがdelete以降なのは論外だが、 void ref() { InterlockedIncrement(&m_ref); } void release() { if (InterlockedDecrement(&m_ref) == 0) { delete this; } } じゃだめだと思ってるやつは何か言ってみろ。 どうせ逃げんだろうけどな。
void ref() { InterlockedIncrement(&m_ref); // A } void release() { if (InterlockedDecrement(&m_ref) == 0) { // B delete this; } } B のタイミングで A が呼ばれた場合。
void ref() { InterlockedIncrement(&m_ref); // A } void release() { if (InterlockedDecrement(&m_ref) == 0) { delete this; // C } } C のタイミングで A が呼ばれた場合。 しかし、危険性において 846 のコードは結局 848 と変わらないな。
おいおい、本当にのこのこ出てきたよ。恥ずかしい奴だ。
>しかし、危険性において 846 のコードは結局 848 と変わらないな。 説明してみろよ。わくわく。 Bのところに行くのは、どういう場合さ?
>849 馬鹿です。
晒しage
>>762は、各オブジェクト毎にロック掛けるって意味ならロックが多量に必要だし、リストにはロック掛けないのか? >リストにロックかけるんだったら、各オブジェクト毎に掛ける必要なし。 >君のような厨には理解で菌だろうがな。 つか、762の時点では、そもそもリストが使われていることが 説明されていないわけで、762の時点で「リストにもロックかけろよ」 と言えるなら、そいつは神
あげてねーじゃん
>855 リストである必要なし。 グローバル変数など共有してれば同じ。 この場合動的じゃなきゃ意味無いが。
何がおなじなんだか、、、
思うんだが、ref() を bool 型にして、呼び出し側で false を受け取ったら取得を諦める ようにはできないのか? bool m_sw1st; // コンストラクタで true に bool ref() { bool ret = true; EnterCriticalSection(&m_cs); if(!m_ref) { if(m_sw1st) m_sw1st = false; else ret = false; } if(ret) ++m_ref; LeaveCriticalSection(&m_cs); return ret; } void release() { EnterCriticalSection(&m_cs); if (--m_ref) == 0) { delete this; } LeaveCriticalSection(&m_cs); } 参照カウンタが 1 始まりなら m_sw1st は要らないけど。
ごめん、無かった事にして。
m_csってメンバー変数じゃないのか? ref()のEnterCriticalSectionでブロックされてるときに deleteされるのは大丈夫か? 首尾よく、ref()でCriticalSectionに入れてもm_refは不定だぞ。
で?849はやっぱり逃げたのか。
ここはすごいITパワーですね。
>838 だから、無いんだって。intのlistを考えてみろよ。 lockしないで、検索処理と、削除処理を併走できるかっつーの。
>864 リストなら丸ごとロックしなくてもできる。
>865 と言うと? >864 おい!あるってぞ。言い返せよ。
別に言い返さないさ。 自身の不明を恥じて、詳細を拝聴するだけサ。
例えば、リストの3番目を削除しようとしている時には、検索処理が4番目以降の要素を 見ているなら同時に動いて問題ない。検索処理が、ちょうど3番目の要素を見ようとしているか 3番目から4番目に移ろうとしている時だけが同時に動けないだけ。 どのみち、要素数とか持っているリストだと同時に複数が書き込めないから、 たかだか一つの要素だけ排他制御できさえすればよい。
リストの項目が増えた時、リスト丸ごとのロックと、項目ごとのロックでは、 どっちが速いんだろうか。
>>869 そういうものの定石を適用すると、リストを示すポインタ値を適当にハッシュして16個くらいの
ロックに分散させる、てな感じにするんだと思うよ。一要素毎にロックを持つのはリソースを食
うし、あまりぶつからない程度に分散させれば十分だから。
>869>870 865が言っているのは、要素毎にロック作らなくても、 同時書き込み無しなら、一つロックがあればいいということだろ。 丸ごとロックしなくても、ロック一つでWriterはReaderと共存(Readerがいなく なるまでまたなくても)できると。
>871 ロックが一つしかないなら、どうやって、 「今削除しようしている所を読んでるreaderがいない& readerは削除しようとしている所へ進入しない」って 保証できるん?
それは、16スレッドが同時に書き込めるのか? 各スレッドが別の要素にアクセスするとして。 リストが要素数なんか持ってても大丈夫? 単純なリストならまだしも、空リストとか管理されてると結局その中の 一つのスレッドしか書き込みできない(というか排他制御が必要な)気がするが。
>872 writerは要素の変更じゃ無くて、要素の追加・削除を行うとして。 writerが削除しようとしている要素とかその次の要素の場所を書いとけば、 readerはそれみて何とかできる気がするが。 writerが削除しようとしている要素はすっ飛ばすとか。 追加は先頭でも最後でも問題起きないと思うが。 どっちにしろ、readerはwriterがする事を知っているのが前提で、 汎用ではなく。
ひょっとして、readerの数だけの、index/pointerを指している 配列と、その配列全体に対するロックがあれば解決できる話 なのか?
>874 それだと、「削除されるべき場所にいるreader」が、 「『リストの次の要素へ』を発行すること」をどう保証するか、 writerはどう検出するかって問題になるとおもうけど、、
50年前の並列処理問題を一から学び直す ドキュソPGのスレはここですか?
>877 ( ´д)ヒソ(´д`)ヒソ(д` )
lock free linked list なんつって
880 :
768だけどさあ :02/11/15 20:02
分からん奴だなあ。 リストの排他制御と、参照カウントの問題と、参照カウントの 排他が全部ごっちゃになっている時点でもう駄目。 まず、リストに複数スレッドからアクセスするなら、そのリストの どこかに排他入れなきゃ駄目なの。次に、問題の共有オブジェクト はリストからの参照の分があるから、リストに繋がっている間は 参照カウントは常に1以上でなきゃ駄目なの。「見付けた」時点では 「リストの方が」排他されているから、この間に参照カウントを増やそうね。 リストの排他が終わった時点で、参照カウントは2以上だから、この後 リストからremoveされても平気だよね。(ここが768の「Bから見える場所に 云々」ということの意味。)第三に、参照カウントも複数のスレッドから 参照されるから、これも排他しなくちゃならないよね。これはさすがに 分かってるみたいだけど。
お前ら無能すぎ。そんな程度で2ちゃん来てんじゃねーよ。
ところで、881は何人目の736ですか?
>>873 何への質問だかわからないけど、16っていうマジックナンバーがあるから
870 だと仮定して答える。
「リストから remove 」等の処理に排他制御をかけるとして、ごく素朴な
リスト全体にたいしてロックが1つ、という状態では競合が起きた場合に
素直にパフォーマンスが悪化する。並列性が高くなればなるほど競合の可
能性は増し、結局並列動作できない場面が出てくる。
その辺をチューニングする場合の定石として、適当にロックの数を増やす
ってのがある。コンテキストスイッチングに比べて排他の対象となる操作
の方が十分重い場合には、寝てるスレッドのことはほぼ無視しても良いの
で、CPU の数+αに分散させれば十分。そうじゃないときは多めにする。
>>849-850 そのタイミングで当該オブジェクトへのアクセスが発生するって思うのは、
参照カウントというものが何であるのかをわかっていないと思う。
そらまあそーいうこともあるだろうケド、その場合呼び出し側がバグって
るわけで。
適当ほざいてんじゃねーよ 帰って寝てろ ワラワラ
881=882だろ。 >880 > 第三に、参照カウントも複数のスレッドから > 参照されるから、これも排他しなくちゃならないよね。 どういう風に?(W
>886 おまえも881だろ。 >884=870 もうちょっと、説明してくれや。
騙ってまで何がやりたいんだか >880 教科書のコピペはやめようね
736増殖中
やめろっての。馬鹿がうつる。
>>880 だぁから、そんなのあたりまえだろ。おまえはしらなかったかもしらんが。
そこを参照カウントに技使って、リストのロックに工夫できないかという話だったのが、
しつこく しつこく しつこーーく 参照カウントのインクリメント不足だと
おんなじ事繰り返す厨の集団攻撃が始まっちまったんだよ。
しまいには、ref()とrelease()に排他制御が無いからだと言い出すドアホまで
何人も出てきやがるし。お前達は、お呼びじゃないんだよ。
reference counting ってのは、そのオブジェクトへの「参照」の数を 数えておいて、ゼロになったら誰も見てないから開放〜てなアイデア。 だからカウントがゼロになった後は誰から参照されておらず、どんな メソッド…メンバ関数も呼ばれないわけです。呼んだとしたらそれは 呼び出し側のバグ。
>そこを参照カウントに技使って、リストのロックに工夫できないかという話だったのが、 736ではそんな話には読めない。最初からそう書けよ。 >おんなじ事繰り返す厨の集団攻撃が始まっちまったんだよ。 自業自得
>そこを参照カウントに技使って、リストのロックに工夫できないかという話だったのが、 どんどん話が変わっているような。しかも参照カウントとオブジェクトを 参照しているリストなんて、参照カウントを増やすこと以外に全然関係 無いから、工夫なんてまず無理だろう。
誰か本物の736を連れ戻してくれよ
>881=882だろ。 違いますよ。
898 :
デフォルトの名無しさん :02/11/15 21:56
だから参照カウントなんて腐った手法使うなって。
>898 ギブアップしたの?(W
だから最初から言ってるだろ? 参照カウントなんて使わずにまともなGC使えや。
参照カウントか、昔よくやってた。懐かしいな。マルチスレッドでうまく解けるか
自信ないけど…。
スレッド 1 がクリティカルセクションに入って参照カウントを 0 にしようとした
瞬間、別のスレッド 2 がカウントアップしようとクリティカルセクションで
ブロックに突入するからまずいんだろうな。同期ブロックに入っている数もカウント
しておいて、参照カウントと同期ブロックスレッド数が 0 になったところで初めて
開放すれば良いんじゃなかろうか。
…でも別スレッドからカウントアップ可能ということはそのスレッドから参照が残っ
てるってことだからやっぱり無理なのか? CPU 負荷などの影響でカウントアップ側の
処理が遅れたらアウトだもんな。んでもスレッド間での参照の「コピー」時にしっかり
カウントアップしてれば問題無いような。
参照カウントと循環参照について IBM に話が載ってるけどこれはガイシュツかいな。
http://www-6.ibm.com/jp/developerworks/java/000721/j_garbage-collection.html
参照を獲得する処理そのものがアトミックでなければいけない。 つまり、ref や release に到達する時点でそのオブジェクトに対する排他制御が かかってなきゃいけない。それらのメソッドに入ってからでは遅い。 Object* List::get(int index){ criticalSections_[index % 4].enter(); Object* o = items_[index]; if(o != NULL){ o->ref(); } criticalSections_[index % 4].leave(); return o; } void List::remove(index){ criticalSections_[index % 4].enter(); Object* o = items_[index]; if(o != NULL){ o->release(); items_[index] = NULL; } criticalSections_[index % 4].leave(); return o; } こんな感じか?
レスがたくさんついていると思ったら、、、
904 :
入門者だけど :02/11/16 01:05
本質的には参照カウントのことは関係なくて、参照が複数スレッドで 共有されていれば、その参照自体にも排他をかけなければならない というだけの話だ、という理解で合ってる?
そもそもスレッド間で参照を代入するときにちゃんと 参照数 +1 してれば ゼロにはならないのでは?
>>906 みんな同期問題の方に目がいっちゃってたね。
>>902 getって削除された要素を飛ばして次の要素を返すんじゃないか?
あと、removeが値を返してるよ。
>>905 その参照を増やす手段がgetなんだけど…
スレッドだけに限らず、とにかく「何ヶ所から指されてるか」 をちゃんと保持しないと。変数に代入したらちゃんと参照カウント 増やせ。
だから、参照カウント法はマルチスレッドにむちゃくちゃ不向き なんだから、まともなGC使えってば...
>>908 スレッド A からスレッド B に参照を代入しようとしている。同時にスレッド C が
参照を開放しようとしている。
最初の時点で参照を持っているのは A と C だから参照数は 2、C がカウントダウン
したところで参照数は 1、そのあと B に代入されてカウントは 2 になる。
これのどこに参照数 0 になる要素があるか答えよ (同期化は当然行っている
とする)。
# と断言して俺が間違ってたら恥ずかしいわけだが…
単なる論理バグで 100 以上引っ張った悪寒
論理バグというより、勉強不足でしょ。
>>911 スレッドの数だけ数えりゃ良いわけじゃないって言うとるに。
ヒープ上のデータ(たとえばリスト)から参照されてて、
そのリストを指しているのはスレッドDだけだったとする。
あんたの数え方だと、スレッドAとBが参照を離したら、
リストから指されてるのに解放されちゃうよ。
また、同じスレッドの中でメソッド呼び出しに参照を渡した
とする。この時にも参照を増やさないと。呼び出された先で
参照が不要になったからって勝手にカウントダウンしたら
呼び出し元が困るだろ。
>>910 でも、C++みたいな言語でGCも怖い気がする。
GCのバグ云々じゃなく、相当気をつけて使わないと、GCと
例外機構やデストラクタが衝突してあぼーん、になりそうで
不安。Cの方がまだしも、処理系の動きが見えやすいだけ、
楽な気がする。
>>914 >あんたの数え方だと、スレッドAとBが参照を離したら、
>リストから指されてるのに解放されちゃうよ。
914をどう読むとそういう数え方になるんだ?
>また、同じスレッドの中でメソッド呼び出しに参照を渡した
>とする。この時にも参照を増やさないと。呼び出された先で
>参照が不要になったからって勝手にカウントダウンしたら
>呼び出し元が困るだろ。
それは弱い参照にするかどうかだよね。呼び出された先が、
どこにもその参照を突っ込まないで、カウントを変えないまま
リターンすれば問題ないわけで。
参照カウントの有難味は無くなるけど。
>>908 いや、index が識別子なのか単なる順序値なのかわからんし、
一応こうしといた。
remove は中途半端になっちまった。引数の型も抜けてるし。
中で release する場合と、オブジェクトを返して外で release する
場合と考えてた。
いくつの「スレッドが」参照してるかなんていう 数え方をするから間違える。 シングルスレッドでも参照カウントはちゃんと増減させるだろ? とにかく「何ヶ所から指されているか」を正しく参照カウント に反映させておかないと。 メソッド呼び出しではたしかに人間が推論して最適化すること はあるね。間違いのもとだけど。
>>914 スレッド D が持つリストからも参照されてるなら初期状態での参照数は 3 だろ。
逝っておくがいくつのスレッドで共有されているかをカウントしているという意味
ではないぞ。
ただ循環参照になってるとどこからも使われてないのに参照数が残ってしまう
だろうな。単純な参照カウントの弱いところだ。
で、736 はどうした。問題は解決したか? とりあえずリスト全体ロックは回避できたんだから、これくらい(複数のロックを使う)で 手を打つのがよいと思うのだが。 あとは、refcount が 0 になってもその場では削除せず、後で回収するくらいしか 無いと思う。もちろん回収の時は、全スレッドを安全な場所で停止させる必要があるが。 っつーかもっといい手があるのかどうか俺も知りたい。
OK 埋め立て成功。 ∧_∧ ∧_∧ (´<_` ) ( ´_ゝ`) / ⌒i さすがだな兄者。 / \ | | / / ̄ ̄ ̄ ̄/ | __(__ニつ/ FIVA / .| .|____ \/____/ (u ⊃
#うわあ。見ないでいたらこんな事態に…
#なんか終息しかけてますけど、まあ話題としては面白いのでいいけど。
ええと、
>>788 が重要な指摘だと思いますよ。
>>786 の「実際には目的のデータであることを確認後」
この確認はどういうコードで行っているのですか?
ぱっと思いつくコードは例えばこうなんですけど。
//目的のデータであることを確認
O3 = O1 ; //ここで既に参照カウントが上がってる!
if (! IsWanted(O3)) {
//O3生成の瞬間にO1が破棄されているとO3に新規データが入っている
//エラー処理
}
O2 = O1 ; //既にO3があるのでO2は要らないけど安全にコピーできる。
なんか私大間違いしてます?
924 :
デフォルトの名無しさん :02/11/16 05:16
しかし良く考えてみると、リスト全体にロックしないと removeはやっぱり出来ないんじゃないかなー。 単方向リストでも、双方向リストでも、配列+ホールでも… 少なくとも「n番目getする」という操作は正しく動かないだろう。 「キーkを持つ要素をgetする」ときも、一部だけロックで出来る?
素直にJava使え。
なんでこんなくだらん事で話を引っ張ってるの? >
>>736
Javaでもコレクションクラスのthread safetyについて考慮してるのは jdk1.2以降ですな。
>>928 thread safety についてというか、1.1 までのコレクションは莫迦でも使えるように
何でもかんでも同期化してただけ。
1.4の日本語ヘルプ >ConcurrentModificationException >... >たとえば、あるスレッドが Collection で繰り返し処理を行なっている間に、 >別のスレッドがその Collection を変更することは通常許可されません。 通常ダメなんだとさ。
この争いに参加しなかった俺は自制心の持ち主
レベル低いだけだろ?(W
>>929 じゃあ、いまでもVectorとか使ってるばかには使わせといた方がいいんですか?
Javaなら少なくともreference countで悩む必要はないね。
>>934 でも、たま〜に使いたくなることあるなぁ。。。
参照カウンタの使い方程度も分からないバカはJavaがお似合いだね
736 はどうしたのよ? 散々人を見下した発言を繰り返した割には、反論できずにだんまりかよ ヘタレやの、おまえ
939 :
デフォルトの名無しさん :02/11/16 23:57
真理を見通す目を使ってこのスレを覗いてみた。そこに見えたものは・・・
938 名前:736 投稿日:02/11/16 22:31
>>937 もういいよ・・・
736マジ死亡!? もっと踊ってくれよ
>>923 あ、違った。O1がBスレッドにあるという時点で
既に参照カウントがアガってなきゃいかんのか。
鬱だ…。
DataType O1;
hr = pDataList->GetItem(index, &O1) ;
if (FAILED(hr)) { /* エラー*/ }
if (IsWanted(O1)
とか。ふむ。確かにリスト側で排他したくなるし、
同時に他スレッドで削除されてると面倒。やっと分かった。
>>941 参照を得る/切るタイミングでアトミックにカウントが上がる/下がる必要が
あるからなぁ。
そうでないと、無効なオブジェクトを参照してしまう。
ならば、参照カウントが 0 でも有効な(というより、無効かどうか判別できる)
ものを作るのも一つの手だな。
bool Object::ref(){
bool valid = false;
cs_.enter();
if(refCount_ > 0){
refCount_++;
valid = true;
}
cs_.leave();
return result;
}
void Object::release(){
cs_.enter();
if(refCount_ > 0){
refCount_--;
if(refCount_ == 0){
garbages__.add(this);
}
}
cs_leave();
}
で、安全なタイミングで(ってそれが一番むずい気も)garbages__(グローバル変数)
の要素を delete してやると。
# 続き。改行が多すぎるって言われちまった。 あるいは、Object ではなく、SharedPtr みたいな入れ物でこれをやっても良い。 SharedPtr のフィールドは Object* を格納する ptr_ と refCount_。refCount_ が 0 になったときに delete ptr_ するけど、 SharedPtr 自体は無効な状態で 残り、garbages__ に入る。 コメントくれ 736。もしくは偉い人。
>>942 ああ。result 返してるよ。ref の最後は return valid; ね。
コンパイルくらいは通すか...
もまいら別スレ立ててそっち逝け
>>943 736でも偉い人でもないが…
ref()がfalseを返したら、いったい何をすればよいんだ?
そもそも、release()で参照が0になるということは、release()を呼んだスレッド
以外からの参照はないはずなのに、他からref()が呼ばれるのがおかしいってば。
リストのgetとremoveが排他制御をちゃんとやれば、そういうことは起きないだろ?
getがロックを離す前にはrefが済んでいる。あるいは、removeが先なら、
参照が他のスレッドに渡ることはない。
947 :
デフォルトの名無しさん :02/11/17 16:21
やっぱり、どう考えてもリスト全体をロックするより無いなー。
Javaを使えば簡単に解決する低次元な問題に 一生悩みつづけるC++プログラマのスレはここですか?
二日留守にしてたからとっくに終ってるかと思えば、まだ続いてたのかよ。こ の736祭は。
>>948 うん
だからオマエには関係ないんよ
どっか逝け、二度と来んな
>>946 いやだから。
List で排他制御をかけずに安全な方法があるかを探してる。
ってあまりやると今度は俺が煽られるかな。
>>952 特殊な場合はあるかもしれんが、一般的なリストのセマンティクスを
ロックなしで一貫性を持って実現するのは無理だろう。
たとえば
「n番目を取り出す」→他のスレッドが先頭を削除したら、戻ったときには正しくない値を返してしまう。
「データxを含む最初の要素を取り出す」→探索中に他のスレッドが先頭にxを
付け加えたら…
>>953 その特殊な場合が知りたい。
そのために、902 の List::remove では、items_[index] = NULL をもって
要素削除としてる。
いや、現実問題、こんなことしてたら、List も Object も、使う側に
知識を要求する、やっかいなクラスになるとは思う。
ただ、そうすることによってパフォーマンスが得られるなら、
それが有効な選択肢になる場合もある。
ってことで、無理問答みたいなことを続けてるわけだ。
っていうか 736 が続けてくれよこれ。
あのさぁ、参照カウントの時に出てきた↓を見てみたんだけど、
http://www.gotw.ca/gotw/045.htm void String::AboutToModify(size_t n, bool bMarkUnshareable /* = false */)
int refs = IntAtomicGet( data_->refs );
if( refs > 1 && refs != Unshareable ) {
StringBuf* newdata = new StringBuf( *data_, n );
if( IntAtomicDecrement( data_->refs ) < 1 ) {
delete newdata; // just in case two threads
} // are trying this at once
else { // now all the real work is
data_ = newdata; // done, so take ownership
}
} else {
data_->Reserve( n );
}
data_->refs = bMarkUnshareable ? Unshareable : 1;
}
の、delete newdataって間違いじゃない?
複数のスレッド(それぞれが参照を持つ)が同時にAboutToModifyを呼び出すと、 それぞれが共有を解除して、独自にデータを持つわけだが、その内の一つは data_->refs が0になるから、元の共有していたdata_の指す先か、newdataの 一方を開放する必要がある。 というのは判るんだけど、AbountToModifyは共有解除と共にsize_t nに データ領域のサイズを拡張しなきゃならんのに、delete newdataでは data_の指す先の領域のサイズはsize_t nだけあるとは限らなくない? ここは、単純に if( IntAtomicDecrement( data_->refs ) < 1 ) { delete data_; // just in case two threads } data_ = newdata; // done, so take ownership じゃないかと思うんだが…
あるいはこうか? if( IntAtomicDecrement( data_->refs ) < 1 ) { delete newdata; // just in case two threads data_->Reserve( n ); } // are trying this at once
ですな。 でも、既にnewdataはサイズn以上で領域確保しているので、 data_を破棄する方が良いかと。 誰も、反論が無いところを見ると、やっぱり間違いと言う事でよろしいか?
パフォーマンスを得るためならreference count法なんて 使っちゃいかんと思うが...
>>958 いいんじゃん。
ところで、次スレって立てんの?
>959 別にリファレンスカウントでアロケーション回数を少なくしてパフォーマンスを稼ごう という事ではなくて、そもそも大域的なデータをマルチスレッドで使う時には意味無いかな?
>>960 マルチスレッドプログラミングの苦労はすべて、
C++を使う事が原因だと結論が出たので、
次スレは不要でしょう。
たてますよー
載せるようなリンク先がねえよ...
>>962 どっちかというと、不要なのはオマエだな
967 :
デフォルトの名無しさん :02/11/19 02:07
じゃあ1000取りでもはじめるか
どれが本スレなんだ・・・。 次スレには全部重複ごめん、次スレはこちら、と書いてあり リンクをたどると無限ループするんだが・・・。
スレ立てもマルチスレッドでやって、排他制御に失敗したのはこのスレですか?
ここの奴らの話は信用ならねーな
つーか「間違えて」3つも立てられるはずないだろ。 明らかに故意に串を差し替えるとか回線を繋ぎ替えるかして 立てたはずだ。 市ねよ。
>>968 素朴な参照カウントモデルは循環参照があると
役に立たないのです
>>972 いえ、それが同じアドレスから3連発したのです
一度目はコネクションタイムアウト
二度目は30秒ぐらいでこちらから停止
三度目で成功
で、気づいたら3つ立ってました(;_;)
一回目の段階で、しばらく待って、スレ一覧をチェックすればよかったんですね。
しばらくスレ立てはやめときます・・・
2ch の調子が悪くてスレ立ての重複が頻発しているらしいよ。
>973 > 素朴な参照カウントモデルは循環参照があると うん、それで? 参照カウントを使って、どんな場合にも使えるクラスを設計しようとしてるならともかく、 循環参照が発生しないデータモデルで使用する場合には、何の意味も無いな。 >972 スレが3つ立ったからって、そんなに迷惑被ったのかヨ? 引きこもりは、攻撃性が強くて困るな。
>>976 「リンクをたどると無限ループ」に引っ掛けたネタに
マジレスされても困るのだが
誰も居ない・・・ ????するならイマノウチ
????
????
????
????
ぬるぽー!! ぬるぽぬるぽぬるぽぬるぽぬるぽ ぬ る ぽ ー っ ! ! !
????