pthread地獄

このエントリーをはてなブックマークに追加
757名無しさん@お腹いっぱい。
スレッド間のコンテキストスイッチってそんなにコストかかるもんなの?
ページ変換テーブルとか切替える必要なさそうだし、たいしたコストは
ないもんだと思ってた。
スタックが分散するから、キャッシュは無駄になりそうだけど。
758名無しさん@お腹いっぱい。:2005/11/17(木) 06:11:58
キャッシュに関しては、量よりも直接のヒット率の方が影響あるんじゃないかな。
中断したタスクを再開したときに、同じプロセッサが割り当てられるとは限らないわけで
全部読み直しに近い場合もあるだろうし。
ただ、その辺はカーネルのスケジューラが出来る限りのことはしてくれると思うし
どの程度差がでるかはわからんね。
759名無しさん@お腹いっぱい。:2005/11/17(木) 07:01:52
> ただ、その辺はカーネルのスケジューラが出来る限りのことはしてくれると思うし

Windowsはこれやってくれないんだよねえ…。
重いプロセスをSMPマシンで動かすと、複数CPU間を行き来して余計に遅
くなったりする。

UNIXで、そのへんちゃんと考慮してくるのって、ある?
760名無しさん@お腹いっぱい。:2005/11/17(木) 07:17:27
アフィニティを手動設定して終わりじゃないの?
761名無しさん@お腹いっぱい。:2005/11/17(木) 07:44:51
>>746
せいぜい「便利なときがある」くらいでしょ。
マイクロソフトお得意の場当たり的スケジューラ特殊化だから。
762名無しさん@お腹いっぱい。:2005/11/17(木) 07:47:18
>>759
一つのプロセス(スレッド)を特定のCPUに割り当てたければ、
processor setを使うのがSolaris流儀。
763名無しさん@お腹いっぱい。:2005/11/17(木) 07:49:41
>>749
> ちゃんとアクティブなスレッド数を調整してくれる機能があるって。

何をどう調節するの?
アクティブじゃなくていいかどうかはどう判断するんでしょう?
後回しにされたスレッドの立場は?
764名無しさん@お腹いっぱい。:2005/11/17(木) 07:54:10
>>760
手動で設定しないと上手くいかない状況は、スケジューラが考慮してい
るとは言えないのなの。
765名無しさん@お腹いっぱい。:2005/11/17(木) 08:22:52
>>763
同時に実行される必要がないタスクだからIOCPに管理されたスレッドを使うのであって
後回しにされるタスクが出るのが嫌なら
普通のスレッドを使えばよいだけ。
766名無しさん@お腹いっぱい。:2005/11/17(木) 08:26:12
>>765
要するに、静的に分類して、優先順位をつけるわけですね?
767名無しさん@お腹いっぱい。:2005/11/17(木) 08:29:11
素のWindows + IISで速い例なんてあるの?
IBM, NEC辺りのはカーネルが素のWindowsとは違う独自バージョンだよ。
奴等ソースコードいじっているから。Databaseの時もそう。
768名無しさん@お腹いっぱい。:2005/11/17(木) 08:29:17
は?
769名無しさん@お腹いっぱい。:2005/11/17(木) 08:34:31
まあいいや。「とりあえずWindowsを叩いときゃいいや」って人は相手にしないどこ。
説明しても理解する気無さそうだし。

大半の人は「良いところもあれば悪いところもある」ってのは分かってるんだから。
770名無しさん@お腹いっぱい。:2005/11/17(木) 08:36:42
おまいら捨てハンぐらい付けたらいかがでしょうか。
何人いるの?
771名無しさん@お腹いっぱい。:2005/11/17(木) 08:40:29
まず自分からつけなよ。
今後全部読み飛ばすようにするから。
772770:2005/11/17(木) 08:44:23
あ、全然別の人だったかな。
自分以外で ? を使っている人って事で勘違いしたかも。
だったらごめんね。
773772:2005/11/17(木) 08:44:59
すまん、>>772は771
774名無しさん@お腹いっぱい。:2005/11/17(木) 08:49:34
IOCPが理論的に最速であることを説明してくれる人きぼんぬ
775名無しさん@お腹いっぱい。:2005/11/17(木) 08:50:29
>>764の言っていることは、
>>765にあらかじめ答えているようなもんだな。
776名無しさん@お腹いっぱい。:2005/11/17(木) 08:58:22
用途の問題だけど。
4CPUとして、
5つの計算をして最後に同期を待つ必要があるのなら
普通のスレッドで並列に実行させれば、1つの計算の1.25倍+αで終わるけど
非同期に1000個のリクエストが来るサーバーでは
最大4つ以上は同時実行せず、1つづつ完全に終了するまで待つ方が
オーバーヘッド分効率が良いというだけ。

あと、IOCPを使ったサーバーでも、普通はlistenするスレッドは独自に動いてるし。
777名無しさん@お腹いっぱい。:2005/11/17(木) 09:06:09
タスク処理時間に偏差がある場合、
平均待ち時間が悪くなるスケジューリングポリシーですね。
処理時間が見積もりやすい科学技術計算辺りが得意分野なのでは?
778名無しさん@お腹いっぱい。:2005/11/17(木) 09:17:56
タスク処理時間の偏差はいいですけど
タスク開始時間の偏差はいかがですか?
779名無しさん@お腹いっぱい。:2005/11/17(木) 10:48:15
>>777
コンテキストスイッチのオーバーヘッドに比べて、
デメリットの方がずっと大きいような…
# webサーバの場合、客を待たせる時間になっちゃうから。

総処理時間合計のベンチマークではいい性能に見えるんだろうけど…
780名無しさん@お腹いっぱい。:2005/11/17(木) 14:07:48
ネットワークの遅延の方が大きいような。
それ以外にも、例えばnagleが有効ならば数百msの遅延が簡単に発生するわけで。
781名無しさん@お腹いっぱい。:2005/11/17(木) 14:23:23
で、結局は道具の使い方の問題だと思うし。

例えば、秒単位の遅延が見込まれる処理(CGIの実行など)は
別にスレッドを動かして、「実行が終わったよ」というシグナルをポストして
他のリクエストと同等のタスクとして終了処理などをするという手もあるし。

そもそも、計算だけで秒単位の時間がかかる処理をWeb鯖が行うというのは
一般的なのかどうか。
(ディスクI/OやDBとの交信など、スレッドがブロックした場合には
次のタスクの実行が開始される、という仕様だから)
782名無しさん@お腹いっぱい。:2005/11/18(金) 14:21:59
>>769
この板でそんな物説明する奴が悪い。シッシッ!
783名無しさん@お腹いっぱい。:2005/11/21(月) 22:50:50
>>1の想像を越えた良スレになりつつある件について
784名無しさん@お腹いっぱい。:2005/11/28(月) 00:11:51
久々に伸びてると思ったが、
unix板の悪い面が出まくりだな。
windowsアレルギーってまだあるんだ。
785名無しさん@お腹いっぱい。:2005/11/28(月) 00:15:46
>>784
具体的に
786名無しさん@お腹いっぱい。:2005/11/28(月) 17:48:29
windows機雷
787名無しさん@お腹いっぱい。:2005/12/18(日) 11:26:49
IOCPがUNIXで実装されないことについての具体的な答えはなかったな。
実装されないことについての必然的な理由が必要というわけではないけど。
788名無しさん@お腹いっぱい。:2005/12/18(日) 11:39:30
789名無しさん@お腹いっぱい。:2005/12/18(日) 15:18:43
と思ったらSolarisにはあるんだな。
http://developers.sun.com/solaris/articles/event_completion.html

これちょっと調べて見るか。
790名無しさん@お腹いっぱい。:2005/12/23(金) 22:26:54
791名無しさん@お腹いっぱい。:2006/01/20(金) 17:39:54
pthread_createして生成されたスレッドが死んでってのを
何十回か繰り返すとpthread_createからENOMEMが帰ってくるんだけど
何が足りないの?
空きメモリは有るみたいだし,生きてるスレッドは1個だけで
RHL9なんすけど.
792名無しさん@お腹いっぱい。:2006/01/20(金) 19:33:13
>>791
detachかjoinしてる?
793名無しさん@お腹いっぱい。:2006/01/20(金) 19:51:05
>>792
>detachかjoinしてる?
791がそれをしてないに、10000 マルク。
794791:2006/01/23(月) 11:10:36
すっかり忘れてた.
795名無しさん@お腹いっぱい。:2006/01/26(木) 13:52:32
pthread をソケット通信で試しに使い始めてみたんですが、どうやらリークしてるっぽくて、

mtrace の結果と objdump を元に、glibc のソースから pthread.c や specific.c をつき合わせたら、
int __pthread_initialize_manager(void)

  /* Setup stack for thread manager */
  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
↑↑↑↑ こいつが1度だけ呼ばれて 8160 byte かかえたまま free されてないっぽいんです。
また実行中に
int __pthread_setspecific(pthread_key_t key, const void * pointer)

void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *));
も free されないので、accept の回数を重ねるたびにどんどん膨らんでいきます。

これについて何か既出の情報ってありますか?
796795:2006/01/26(木) 14:20:07
うおぉぉぉ 真上に解決策が書いてあるじゃまいか orz

pthread_detach し忘れてますた
スレ汚しすまそ
797名無しさん@お腹いっぱい。:2006/01/27(金) 01:37:41
そういえば、joinでは複数のスレッドを待てませんが、
どこかでデッドロックを避けるためだと読んだことがあるのですが、
具体的には書いてありませんでした。
知ってる人いますか?
798名無しさん@お腹いっぱい。:2006/01/28(土) 13:36:33
>>797
どこに書いてあった?
799名無しさん@お腹いっぱい。:2006/01/28(土) 23:04:41
>>798
どこだったか思い出せないのですが
「昔はwaitallだかwaitanyの様なのがあった」らしいです。
ゾンビネタを読んで疑問を思い出しました。
800名無しさん@お腹いっぱい。:2006/02/23(木) 16:39:36
<ちら裏>
pthread を使ったソケットプログラム。

accpet したソケット fd を子スレッドに void* で渡す、定番のコードのつもりだったんだけど、
void * のポインタなんだからと思って

fd=accept(listen, &addr, &addr_len);
pthread_create(&id, NULL, child_func, (void *)&fd);

と参照渡しをしたところ、同時多数アクセスがあったとき、親スレッドと子スレッドで異なる
fd にアクセスする奇怪現象に悩まされた。子スレッドが fd を実際に読むする前に、
親側では次の accept が呼ばれて fd が書き換わってたというオチ。素直に

pthread_create(&id, NULL, child_func, (void *) fd);

と値渡しにすることで解決。

お粗末。
</ちら裏>
801名無しさん@お腹いっぱい。:2006/02/23(木) 19:59:51
粗末だな……
802名無しさん@お腹いっぱい。:2006/02/26(日) 01:08:49
accept() してから pthread_create() よりも、

「まずは listen() したソケット用意して、
そいつを非ブロックモードに設定して、
同時接続最大数のスレッドを pthread_create() して、

生成されたスレッドそれぞれで mutex 獲得して、
listen ソケットを accept() して、
mutex を解放。

accept() の戻り値が 0 以上だったら、その戻り値を接続相手との通信ソケット記述子に使用する。
通信終了したら accept() の戻り値を close() する。

mutex 獲得に戻る。」

が、いいんじゃないの? ちがうの? いつも、こーゆーふーにしてたよ…
803名無しさん@お腹いっぱい。:2006/02/26(日) 02:51:51
>>802
非ブロックモードにしないでみんなで
acceptでスリープするのはどう?
あとmutexは短時間の排他に最適化されるのでmutex+acceptはまずい。
sem_wait/postか、condvarをつかう。
804名無しさん@お腹いっぱい。:2006/02/26(日) 16:03:25
>>803
そのやり方は、設計に依存するんじゃね?
805名無しさん@お腹いっぱい。:2006/02/27(月) 02:05:15
>>802
おいおい……それ思いっきりビジーループしてるじゃねえか。

却下だ、却下。
806名無しさん@お腹いっぱい。:2006/02/27(月) 11:04:18
>>805
802が暗黙の了解で select/poll してると想像してみるテスト
807名無しさん@お腹いっぱい。:2006/02/28(火) 03:11:33
>>805
> >>802
> おいおい……それ思いっきりビジーループしてるじゃねえか。
> 却下だ、却下。
mutex の獲得で待ち合わせしててもダメなの?
808名無しさん@お腹いっぱい。:2006/02/28(火) 07:30:48
>>807
mutexをそういう風に使ってはいけないと婆さんが言ってました。
809名無しさん@お腹いっぱい。:2006/02/28(火) 08:40:23
acceptしてそのまま処理するのが普通なの?

私はaccept専用スレッドつくって、acceptしたら別スレッドに処理させるかな。
そしたらacceptスレッドは、接続があるまで(acceptでもselectでも)寝てればいいし。

どうでもいいのなら、1接続1スレッドでスレッド使い捨て、
まじめに作るなら、1スレッドで複数の接続を扱うようにする。
スレッド数はCPU数とかに応じて適当に決める。


でも、みんなでacceptするやり方だと、
acceptすべきかどうか判断するのが簡単になりそう。
自分が上限まで接続を扱ってたら、acceptしなければ良いだけだし。

acceptして放置するのと、acceptしないのってどっちが良いんだろうか…
810名無しさん@お腹いっぱい。:2006/02/28(火) 11:02:11
ヘビーロード、特に接続到着について、サーバは両者の組み合わせ。
811名無しさん@お腹いっぱい。:2006/02/28(火) 19:50:56
>>809
確か、accept()をすると、SynAck返したはず
だから、実行するのとしないのとでは挙動に違いがでるよ。
812名無しさん@お腹いっぱい。:2006/02/28(火) 21:51:38
うん。そこまではわかるんだけど、
いずれ処理してやれるなら、とりあえずacceptした方が良いのかな。
813811:2006/02/28(火) 22:22:57
>>812
いやだからさ、TCPコネクションにタイムアウトさえしなければ
どっちでもいいと思うぜ。
814名無しさん@お腹いっぱい。:2006/02/28(火) 22:32:10
>>812
listen状態のsocketのbacklogを伸ばす方法もある。
815名無しさん@お腹いっぱい。:2006/02/28(火) 22:41:43
>>811
ACKは、acceptしなくても返すんじゃないのか?
listenのバックログに余裕がある間は。
http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-3.html#ss3.3
って、その事だと思うんだけど。

とすれば、単位時間に処理できる限界を超えない限り、
accept自体は急ぐ必要は無いでしょ。
816811:2006/02/28(火) 23:12:51
>>815
あう。
そうだったね。スマソ > 809
817811:2006/02/28(火) 23:21:52
といっても、accept()を思い出したように処理してるアプリなんて今まで見た事ないなぁ。
818名無しさん@お腹いっぱい。:2006/03/01(水) 00:01:41
「accept自体は比較的重い処理なので
listenしているスレッドではacceptableというイベントのみを検知して
accept自体はワーカースレッドに投げて処理させる」
という方式は、どこかで見たよ。

「acceptが重い処理」というのは、たぶんWinsockのIOCPとかAcceptExとかその辺を調べている時に
見たんだと思うけど、accept時のカーネル内部での処理の重さは、
Windowsでもそう変わらないでしょ、たぶん。
819名無しさん@お腹いっぱい。:2006/03/01(水) 00:45:59
acceptが重いんじゃなくて、
acceptをたくさん動かすためにはその分プロセスが必要だからでしょ?

Solarisなんかはthread単位で大丈夫だけれど、それでもselect/pollよりリソース食う。
apache2はその辺いろいろカスタマイズできるよね。
820名無しさん@お腹いっぱい。:2006/03/01(水) 01:31:00
なんでacceptとプロセスが関係あるのさ?
>>818がWindowsの話なら、マルチプロセス型のサーバーなんか絶対あり得ないのに。
821名無しさん@お腹いっぱい。:2006/03/01(水) 15:07:59
>>818
他のOSは知らんけど、Linuxに限って言うとacceptはそんなに重い処理では無いよ。
822名無しさん@お腹いっぱい。:2006/03/01(水) 20:28:05
>>821
どんな OS でもおおむね以下のような処理になると思われる.

受信割り込みから起こされた処理が, コネクション確立を確認
したら, その情報を listen queue につないで, accept してる
奴を起こす

accept は
while (listen queue が 空)
寝る
socket 作って listen queue から取り出した情報を設定(これ
は受信側でやってもいいし...)
該当 socket をプロセスなりファイルディスクリプターなり
に関連付する
上記 socket から peer address 情報引っ張ってきて引数で
指定された場所に書き込む

結局 accept って寝てるだけじゃん
823818:2006/03/01(水) 23:50:58
>>822
他のOSも似たような実装だと思うけど、
そうすると、818がWindosにおいてacceptが比較的重いと言ってるのが謎。
824823:2006/03/01(水) 23:52:32
名前欄間違った。
818でなくて、821ね。
825名無しさん@お腹いっぱい。:2006/03/02(木) 06:31:24
>>822
> while (listen queue が 空)
> 寝る

signal_wait(listen_queue);

とevent駆動型になっている
826名無しさん@お腹いっぱい。:2006/03/02(木) 06:32:29
>>823
あんなの>>818の勘違いでしょ。
827822:2006/03/02(木) 08:07:32
>>825
> signal_wait(listen_queue);
やってること(つかセマンティック)はいっしょじゃん.
要は寝てると...
828名無しさん@お腹いっぱい。:2006/03/02(木) 08:32:04
whileで書くとbusy waitみたいだからいくない
829名無しさん@お腹いっぱい。:2006/03/02(木) 09:38:43
>>828
寝るって書いてあるのに busy wait も何もあったもんじゃないような気が...
830名無しさん@お腹いっぱい。:2006/03/02(木) 15:57:49
>>828
>whileで書くとbusy waitみたいだからいくない
それ既成概念にとらわれているよ。
オープンソースなカーネル見ればわかるよ。
831名無しさん@お腹いっぱい。:2006/03/02(木) 16:50:43
init() の main が for(;;); で終わってるやつ?
832名無しさん@お腹いっぱい。:2006/03/02(木) 17:39:31
それなんの奴?FreeBSD?
833名無しさん@お腹いっぱい。:2006/03/02(木) 22:33:27
1) acceptするスレッドは1匹だけ
  cond varで餌待ちのワーカースレッド多数
2) 多数のスレッドみんながaccept

どっちが性能/設計的に良い?
834名無しさん@お腹いっぱい。:2006/03/02(木) 23:26:26
>>833
スレッドが多すぎると (1) の方が不利な希ガス
835名無しさん@お腹いっぱい。:2006/03/03(金) 00:04:52
でも、2)は、1接続が1スレッドを占有する方式の時じゃないと使いにくいでしょ。
細切れタスク(例えばKeep-AliveなHTTPでの1リクエスト等)をスレッドプールに渡す方式にするなら
必然的に1)になるんじゃないかな。
836名無しさん@お腹いっぱい。:2006/03/03(金) 06:40:31
SMP なんかだと, accept する thread 増やすと client から見た
時の応答性能は上がると思われるので, accept する thread は
CPU の個数以上/餌待ちワーカースレッド多数ってのが現実的な解
ではないかと, 愚考してみる.
837名無しさん@お腹いっぱい。:2006/03/03(金) 16:58:20
だから、
鯖がACKを返し、それをクライアントが受け取ってからデータを送信、という
ネットワークの往復期間内にacceptが完了するのであれば
応答性なんて全然変わらないと、>>815で指摘されてるでしょ。
838名無しさん@お腹いっぱい。:2006/03/03(金) 19:56:41
>>837
いや、ある条件においてはそれが覆されると思う。

それは、複数のNIC and IPを持つサーバの場合だ。
複数NICで複数IPアドレスを割り振ったら、>>836のやり方でも良いと思うよ。
839名無しさん@お腹いっぱい。:2006/03/03(金) 21:30:15
その辺はapache2のチューニング報告でよく語られてますよん。
カーネル内HTTPサーバのTUXではどうなのか知りたいところだが、
いいベンチマーク報告が見つからない。
840名無しさん@お腹いっぱい。:2006/03/03(金) 22:48:39
>>838
要するに帯域オーバの場合だな。
841名無しさん@お腹いっぱい。:2006/03/07(火) 16:41:21
>>820
昔は acceptしてから子プロセス作って...って感じだったから、それとごっちゃになってるんじゃね。

俺自身が関わる範囲では
>>809の「私はaccept専用スレッドつくって、acceptしたら別スレッドに処理させるかな」
で十分だ。
842名無しさん@お腹いっぱい。:2006/03/08(水) 07:09:55
>>841
>>昔は acceptしてから子プロセス作って

今だって、ftp、telnet みたいに子プロセスを作るのは普通にある
Webサーバみたいに短時間でコネクションが切れちゃうものは、
スレッドで済ませる場合があるだけ。

あと、>>820>>841 は accept 後の並列と、accept の並列を勘違いしてる
843名無しさん@お腹いっぱい。:2006/03/08(水) 10:42:30
>>842 今だって、ftp、telnet みたいに子プロセスを作るのは普通にある
そうだね。

まぁもともとの >>800 は、ローカル変数 fd をスコープはずれてからもアクセス
しようとしてるっつう並列処理以前の話だがな

844名無しさん@お腹いっぱい。:2006/03/08(水) 16:27:24
>>842
>>820のどこが勘違い?
勘違いしてるのは>>819だろ
845名無しさん@お腹いっぱい。:2006/03/08(水) 16:30:16
あ、違うな。
>>818はacceptの重さを問題(真偽はともかく)なのに
>>819がプロセスの重さに勝手に置き換えて、
それを>>820が指摘しているだけだな。
846名無しさん@お腹いっぱい。:2006/03/10(金) 23:44:49
linux って clone つかって pthread 実装してるでしょ?
PID も違うものが割り当てられる。。。そこまではいい。

#include <pthread.h>
void *func(void *arg)
{
 printf("child %d\n",getpid());
 while(1);
}
main()
{
 pthread_t th;
 printf("parent %d\n",getpid());
 pthread_create(&th,NULL,func,NULL);
 while(1);
}


これ動かすと、
$ ./sample
parent 29220
child 29222
$ /sbin/pidof sample
29222 29221 29220
pid が 3つ見える。29221 の正体はなぞ。なにこれ?
847名無しさん@お腹いっぱい。:2006/03/10(金) 23:57:56
2.6系使いなよ。
848名無しさん@お腹いっぱい。:2006/03/11(土) 00:07:21
>>846
noneNPTLのマネージャースレッドでは?
849名無しさん@お腹いっぱい。:2006/03/11(土) 00:37:53
>>848
dクス
そういうことみたい
$ getconf GNU_LIBPTHREAD_VERSION
linuxthreads-0.10
850名無しさん@お腹いっぱい。:2006/03/15(水) 06:53:20
SIGHUP を受けて設定ファイル等を再読み込みの要求があったときに
全てのスレッドがループの所定の位置(例えば先頭)に戻って来るまで
待つような同期処理はどうしますか?

signal ハンドリング用のスレッドを回しておいて、そいつが SIGHUP を
受けると、各ループが作業中確保していた mutex を奪取するというのが
考えられるんですが・・・・
851名無しさん@お腹いっぱい。:2006/03/16(木) 17:47:36
>>850
mutexをとれる保証はないのでrwlockでバリアするのがよいかと。
852名無しさん@お腹いっぱい。:2006/03/16(木) 19:03:57
>>851

ありがとうございます!
試してみます
853名無しさん@お腹いっぱい。:2006/05/31(水) 23:16:24
stl の string って MTsafe じゃないの?
g++ aaa.cpp -I /usr/pkg/include/stlport -L /usr/pkg/lib/ -lstlport_gcc
-D_PTHREADS -D__STL_PTHREADS -D_THREAD_SAFE -D_REENTRANT -g

using namespace std;

list<string> l;
pthread_mutex_t mut;

void *
do_add(void * arg) {
printf("thread arg = %s\n", (char*)arg);
pthread_mutex_init(&mut, NULL);
string aaa = "aaa";
int count_clear = 0;
while (1) {
int ret = rand() % 2;

pthread_mutex_lock(&mut);
if (ret) {
l.clear();
count_clear++;
}
l.push_back(aaa);
pthread_mutex_unlock(&mut);
printf("count_clear=%d\n", count_clear);
}
return NULL;
}
854名無しさん@お腹いっぱい。:2006/05/31(水) 23:18:12
つづき

int
main ()
{
pthread_t thread;

pthread_create(&thread, NULL, do_add, (void *)"t1");

while (1) {
if (!l.empty()) {
for (list<string>::iterator it = l.begin();
it != l.end();
it++) {
// printf("l->c_str() = %s\n", it->c_str());
assert(strcmp(it->c_str(), "aaa") == 0);
}
}
}
return 0;
}
855名無しさん@お腹いっぱい。:2006/06/01(木) 01:53:54
856名無しさん@お腹いっぱい。:2006/06/01(木) 01:57:46
857名無しさん@お腹いっぱい。:2006/06/01(木) 06:44:57
そのプログラムって、aaaをいじってないから、
stringがMTsafeかどうか関係ない気がするんだけど、見落としてる?
858名無しさん@お腹いっぱい。:2006/06/01(木) 06:56:03
containerがMT-Safeかどうかと、
containerをいじった時に、既存のiteratorが有効なままかという概念は別。
859名無しさん@お腹いっぱい。:2006/06/01(木) 08:48:23
どういう結果を期待してるのか書いてないけど、
aaaじゃなくてbbbと印字されるんだったらstringが(MT)Safeではないことになるかな。
860名無しさん@お腹いっぱい。:2006/06/01(木) 11:25:47
>>854
main() も l にアクセスするのにどうしてmain内では排他制御してないの?
861名無しさん@お腹いっぱい。:2006/06/01(木) 13:21:51
>>853
mutは何を保護するためのmutexですか。
862名無しさん@お腹いっぱい。:2006/06/01(木) 16:54:49
Goolge Summer of Code 2006で、
lock free C++ containerやるみたいね。
863名無しさん@お腹いっぱい。:2006/06/02(金) 23:34:46
ああ、ありがとみなさん
かいたあと、あれ、 iterator をいじってる最中に、
it がさしている先ってかわる可能性あるなと。。。
>> 857 さんの意見がそのとおりで
かきなおしました。

で、main で l をさわっているのに、Mutex してなかった理由は、ここらへんよんでいて
The SGI implementation of STL is thread-safe only in the sense that
simultaneous accesses to distinct containers are safe, and simultaneous
read accesses to to shared containers are safe. If multiple threads access a
single container, and at least one thread may potentially write, then the
user is responsible for ensuring mutual exclusion between the threads
during the container accesses.

でなにをとちくるって読んでいたのか。。というと
read はあれか、共有していても、だいじょぶなのか?とか英語をまったく
よんでない状態でした。。。

2 行目をみればわかるとおり、access してる最中は、user は、
mutual exclusion をやらなきゃならんとかいてあったりしますです。。。
スレよごしてごめんなさいです。

864名無しさん@お腹いっぱい。:2006/06/02(金) 23:36:29
で、かきなおしました
int
main ()
{
pthread_t thread;

pthread_mutex_init(&mut, NULL);
pthread_create(&thread, NULL, do_add, (void *)"t1");

while (1) {
pthread_mutex_lock(&mut);
if (!l.empty()) {
for (list<string>::iterator it = l.begin();
it != l.end();
it++) {
// printf("l->c_str() = %s\n", it->c_str());
assert(strcmp(it->c_str(), "aaa") == 0);
}
}
pthread_mutex_unlock(&mut);
}

return 0;
}

これで、20 時間くらいまわしても大丈夫でした。
ありがうございました。
865名無しさん@お腹いっぱい。:2006/06/02(金) 23:37:34
ああ、>> 858 さんだおゆるしを。。。
866858:2006/06/02(金) 23:49:42
なんかおかしいと思ったw
867名無しさん@お腹いっぱい。:2006/06/04(日) 17:14:18
Linux で複数のスレッドから共通に呼ばれることを目的とした自前の syslog 関数 (mysyslog) を作って、
その始まりと終わりで mutex の lock/unlock をやっているのですが、負荷が小さいときは問題が
ないのですが、負荷をかけてゆくとなぜか segmentation fault してしまいます。

$ uname -a
Linux hoge 2.4.31-0vl1.12smp #1 SMP Mon Dec 26 22:01:47 JST 2005 i686 unknown
$ rpm -q glibc
glibc-2.3.3-3vl1.3

コアダンプは以下の通りです。

Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/i686/libpthread.so.0...done.
Loaded symbols for /lib/i686/libpthread.so.0
Reading symbols from /lib/i686/libc.so.6...done.
Loaded symbols for /lib/i686/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
#0  0x400258b0 in sem_timedwait () from /lib/i686/libpthread.so.0
(gdb) bt
#0  0x400258b0 in sem_timedwait () from /lib/i686/libpthread.so.0
#1  0x400225cc in pthread_mutex_unlock () from /lib/i686/libpthread.so.0
#2  0x08054e50 in mysyslog (priority=7, msgformat=0x805c5c0 "send_proc() unlocking mutex_sleep")
    at syslog.c:117
868名無しさん@お腹いっぱい。:2006/06/04(日) 17:21:27
ソース貼れば、的確なレスがつくぞ
869867 続き:2006/06/04(日) 17:21:55
自前の syslog 関数です。一部省略してます。 syslogfp は別途 myopenlog で開いた状態で呼ばれています。
char hostnmame[MAX];
pthread_mutex_t mutex_log = PTHREAD_MUTEX_INITILIZER;
void mysyslog(int priority, const char *msgformat, ... )
{
 va_list args;
 char format[MAX], newname[MAX];
 time_t tsec;
 struct tm t;
 struct stat stat_buf;
 const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
 if(syslogfp == NULL)
    return;
 /* get time of this call */
 tsec=time(NULL);
 gmtime_r(&tsec,&t);
 /* filename */
 pthread_mutex_lock(&mutex_log);
 if (priority <= cf.loglevel){
    va_start(args, msgformat);
    sprintf(format,"%s %d %02d:%02d:%02d %s %s[%d]: %s\n",
        mon[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,  hostname, logident,  (int)getpid(), msgformat);
    if(priority <= LOG_INFO){
      vfprintf(syslogfp, format, args);
      fflush(syslogfp);
    }
  }
  pthread_mutex_unlock(&mutex_log);   <----  ここで seg. fault
  return;
}
870869 の続き:2006/06/04(日) 17:27:14
ちなみに呼び出し側 send_proc() の該当箇所は

  pthread_mutex_lock(&mutex_sleep);
  sleep_mode = 1;
  mysyslog(LOG_DEBUG, "send_proc() unlocking mutex_sleep");  <--- 呼び出し行
  pthread_mutex_unlock(&mutex_sleep);

こんな感じです。mutex のデバッグのために呼び出したログ関数で問題が起こっています。
何か助言頂けると幸いです。
871867:2006/06/04(日) 17:49:13
ちなみに、seg. fault は違う場所でも発生して、ホスト名解決のためにライブラリ関数を

    if ( gethostbyname_r(hostname, &host,buf, sizeof(buf), &result, &h_errnop) != 0 ){

のように呼んだ場所でも、mutex 周辺が原因のような segmentation fault を起こします。
引数は全て実体が正常に確保されています。以下、そのときのコア

Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/i686/libpthread.so.0...done.
Loaded symbols for /lib/i686/libpthread.so.0
Reading symbols from /lib/i686/libc.so.6...done.
Loaded symbols for /lib/i686/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
#0  0x400259a3 in sem_timedwait () from /lib/i686/libpthread.so.0
(gdb) bt
#0  0x400259a3 in sem_timedwait () from /lib/i686/libpthread.so.0
#1  0x400225cc in pthread_mutex_unlock () from /lib/i686/libpthread.so.0
#2  0x431aeb0c in _nss_files_gethostbyname_r () from /lib/libnss_files.so.2
#3  0x4015e45b in gethostbyname_r () from /lib/i686/libc.so.6
872867:2006/06/04(日) 17:53:35
たびたびすいません。

>>869
pthread_mutex_t mutex_log = PTHREAD_MUTEX_INITILIZER;


pthread_mutex_t mutex_log = PTHREAD_MUTEX_INITIALIZER;

の転記ミスでした。
873名無しさん@お腹いっぱい。:2006/06/04(日) 18:27:17
va_end()が抜けて無いか?
原因は、負荷を与えた時にスタックが枯渇して落ちてるんじゃないかな?
恐らくgethostbyname_r()も(タイミングが悪いと)その影響で落ちてるのだと思う。


↓こうしたらどうか?

 if (priority <= cf.loglevel){
    va_start(args, msgformat);
    sprintf(format,"%s %d %02d:%02d:%02d %s %s[%d]: %s\n",
        mon[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, hostname, logident, (int)getpid(), msgformat);
    if(priority <= LOG_INFO){
      vfprintf(syslogfp, format, args);
      fflush(syslogfp);
    }
    va_end(args);    <ーこれが抜けてる
  }
874873:2006/06/04(日) 19:01:27
ん??
それ以前に可変個引数の使用方法がおかしいぞ。
875867:2006/06/05(月) 10:22:43
>>873-874

指摘ありがとうございます!

sem_timedwait とかに気をとられて glibc のソース解読とかを始めそうになってましたが
普通の処理でコードが間違ってそうですね・・

なんだか pthread そのものの問題じゃなさそうですが、解決したらまた報告します!
876名無しさん@お腹いっぱい。:2006/06/05(月) 20:45:08
>867
MAXが足りてないオチ。
だから、n付き関数呼べとあれほど(ry
877867:2006/06/06(火) 23:07:34
867 です。解決報告をしたいところだったんですが、指摘して頂いた点に留意してコードを以下のように変えても依然同じ場所 (sem_timedwait) で seg. fault します。
backtrace で変数の中身をを見ても、ここでは MAX があふれてるとかの問題は起きていません。あと、ulimit も全て unlimited にしてみましたが、状況は変わっていません。

void mysyslog(int priority, const char *format, ... )
{
 va_list ap;
 char msg[MAX],  buf[MAX];
 time_t tsec;
 struct tm t;
 const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

 if(syslogfp == NULL)  return;

 tsec=time(NULL);
 gmtime_r(&tsec,&t);

 pthread_mutex_lock(&mutex_log);
 va_start(ap, format);
 vsnprintf(buf, MAX, format, ap);
 va_end(ap);
 snprintf(msg, MAX, "%s %d %02d:%02d:%02d %s %s[%d]: %s\n",
  mon[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
  hostname, logident,  (int)getpid(), buf);
 if(priority <= LOG_INFO){
  fprintf(syslogfp, "%s", msg);
  fflush(syslogfp);
 }
 pthread_mutex_unlock(&mutex_log);

 return;
}
878873:2006/06/07(水) 02:38:36
Valgrind を使ってみたらどうだろうか。

参考サイト
http://221.112.61.214/~kzk/column/valgrind-tools.html
http://valgrind.org/
879867:2006/06/07(水) 02:51:41
>>878

ありがとうございます!
色々ツールの必要性を感じてたとこなのでこの手の情報はとても助かります!
880名無しさん@お腹いっぱい。:2006/06/07(水) 13:59:01
>>873 >>876

867 です。

全てのコードをお見せできるわけじゃないので表現しづらいのですが、
valgrind を使ったところ、コード貼ったのとは違う場所のソケット通信の部分で
points to uninitialized buffer と出てきたので、送信バッファを隈なく
初期化するようにしたら症状が治まりました。裏で何が起きてるのか
まだ把握してませんが、スタックが侵食されてたのかもしれません。

結局のところ pthread とは全く関係ない部分の問題でスレ汚ししてしまいましたが、
おかげ様で解決しました!ほんとう、助かりました!
881名無しさん@お腹いっぱい。:2006/06/07(水) 14:49:42
たまたま症状が出にくくなっただけで、問題が解決されたわけではない気がするのは、気のせいだろうか。
882873:2006/06/07(水) 15:03:17
>>880
それはよかった。

けど、
>裏で何が起きてるのかまだ把握してませんが、スタックが侵食されてたのかもしれません。
今後の為にも、ちゃんと把握しておいた方がいいぞw
883名無しさん@お腹いっぱい。:2006/06/07(水) 15:21:47
その送信バッファの近所でオーバーランしてる予感
884867:2006/06/07(水) 16:13:04
>>881 >>882 >>883

あう、その通りですね。
valgrind 強力なんで虫つぶしに励みます。
885名無しさん@お腹いっぱい。:2006/06/14(水) 02:18:36
Linux 以外にしたら解決したりして。
886名無しさん@お腹いっぱい。:2006/07/05(水) 23:35:15
887名無しさん@お腹いっぱい。:2006/07/07(金) 09:03:55
>>886
流し読みした限りをめちゃくちゃ乱暴に要約かつ意訳すると、

rwatoson: libpthreadにあってlibthrにない機能はもうないし、現実のアプリ
ケーションはlinuxのスレッドモデルをみんな基本にしてるし、でのベンチ
マークも上だから変更しようよ。

deischen: libpthreadにあってlibthrにない機能を追加してくれたらね。1:1モ
デルじゃ難しいだろーけど。

jb: libpthreadのその機能とかはi386以外のアーキテクチャで動いてんのかよ。

deischen: 知らない。POSIX標準に適合させたいだけだよ。他のアーキテクチャ
でのlibpthread向けの作業は誰かやって。

davidxu(libthrの作者): (最初のrwatosonメールに)賛成。デフォルトにしよう。

jb: (deischenに対して)ほとんどのlinux開発者(アプリを含むと思われる)は
たぶん、POSIXが何なのかすら知らねーよ。

devidxu: (deischenの最初のメールに対して)あんたの言うようにsystem scope
threadをlibpthreadに追加すべきじゃないと思うし(kernelの修正とかしなきゃ
現実的じゃない)、そんな機能は削除、削除。
それに、そんな方法だと現実の世界のほとんどのアプリケーション性能を改善
するためにhard realtimeが必要にだね。hard realtimeが必要ならなんで
FreeBSDを使ってんの?
あとさ、最近のCPUフレンドリーなスケジューラをユーザランド上に導入するの
って簡単じゃないと思うし。
(1:1モデルじゃ難しいと言われたことに対して)不可能じゃないし、少しずつや
ってるよ。
888名無しさん@お腹いっぱい。:2006/07/07(金) 09:06:57
deischen: (devidxuに対する返信)(system scope threadに関して)system
scopeじゃないよ。
(ユーザランド上のスケジューラについて)KSEが良き計らってくれるから
影響ないね。

以下 devidxuとdeischenの既に対応してるとか、hardworkだとか、その機能
はどこの担当だとかが続く中で、rwatsonのaceept, i/o, i/o, i/o, ..., close
とか、kip.macy(sun4vのport作業担当)がKSEの移植でグチったり、 Sunのエ
ンジニアがscheduler activationsやめたのは重要なアプリケーションはみん
なlinux方式を仮定してるからだけど、誰かFreeBSD方式ととlinux方式のちゃ
んとした比較教えてとかいったり、julianのKSE講座があったり、peterが
bike_schedという名前はこのスレッドのことじゃないよとかいいながら
perforceでやってるスケジューラ周りのpatchを提出してるってことでOK?

そのうちMLで結論でたら誰か報告おねがい。
俺の結論としては世の中みんなLinuxに振り回されっぱなし。
いまさらながらPOSIXの存在価値っていったい……。
889名無しさん@お腹いっぱい。:2006/07/07(金) 09:39:45
Linux vs POSIXじゃなくて、1:1 vs M:Nでしょ?

> 現実のアプリケーションはlinuxのスレッドモデルをみんな基本にしてるし

こういう発言が誤解を招くのだろうが。

しかもdefaultを1:1にしようって話で、
M:Nは金輪際辞めろっていうわけでもないし。

上手く両方共存していって欲しいが、人的リソースがきついかな。
890名無しさん@お腹いっぱい。:2006/07/07(金) 10:29:43
すまん、誤解させたようだ。結論と書いてある部分は無視してくれ。
その部分は、単になんでもLinuxが採用したものが標準なっていくっ
てグチろうとした部分の削除し忘れだ。

それとも、その部分以外でLinux vs FreeBSDに読めた?
徹夜明けで頭はたらいていないんで、そーなら、なおさらごめん。
891名無しさん@お腹いっぱい。:2006/07/19(水) 16:44:29
すいません。プログラム板の「マルチスレッドプログラミング相談室」から引っ越して来ました。
質問内容とこれまでの議論はこちらを見てください。
http://pc8.2ch.net/test/read.cgi/tech/1130984585/627-659
Linux での pthread と accept() の動作についてなんですが、分かる人居ますか?
(このスレの上の方で近いことが既に議論されていたようですが)

一応一つのスレッドでだけ accept() をして続きの処理は待機させておいた
スレッドにやらせるという方法で回避できたので現在は困ってはいません。
現在は何故そうなるのかという疑問だけが残った状態です。
892名無しさん@お腹いっぱい。:2006/07/19(水) 17:13:48
> 現在は何故そうなるのかという疑問だけが残った状態です。

Linux板の方がいいんじゃないの?

893名無しさん@お腹いっぱい。:2006/07/19(水) 17:37:10
>>892
それってpthreadは無関係ってこと?
894891:2006/07/19(水) 17:53:50
>>892
そうですかね。
Linux と pthread とネットワーク全てに絡む話なので、何ともいえない
ところなんですが。(やっぱり Linux の pthread 実装がクソだったという
結論になる可能性もないわけではないですが…)。

ところで Linux ではなく UNIX (Solaris) とかは複数スレッドからの
accept() は問題無く動くんでしょうか?
(なんとなく動きそうな気はしますが)
895名無しさん@お腹いっぱい。:2006/07/19(水) 19:12:54
>>891
現実逃避をかねて実験してみた. FreeBSD でやると別の fd 返してくる.
手元に Linux ないんで, 動作の比較はできなかったけど...
スレッド起こす側は下みたいな感じでいいんだろ?

main(...)
{
...
k = socket(PF_INET, SOCK_STREAM, 0);
// bind/listen する
// ioctl なり fcntl なりで nonblock にする

pthread_create(&t0, 0, thr, (void *)k);
pthread_create(&t1, 0, thr, (void *)k);
}

896891:2006/07/19(水) 19:59:00
>>895
そうです。そんな感じです。

そうですか。やはりうまく行きますか。
(やっぱLinux板行った方がいいかな・・・)
897名無しさん@お腹いっぱい。:2006/07/19(水) 20:10:39
原因がLinuxのバグだとしても、作りは相当変だよ。
だいたいnon-blockingにして闇雲にポーリングするなんてどうなのよ。
1個のスレッドでイベントのあるときだけaccept()するだろ普通。
898名無しさん@お腹いっぱい。:2006/07/19(水) 22:40:49
NPTLなのか?
899名無しさん@お腹いっぱい。:2006/07/19(水) 22:42:25
linux-2.6.17のコード見てみたけど、fdの割り当てはfd table共有してる限り、
同一のspin_lockで排他してるからだぶることなさそうなんだがなぁ。
accept()で返されてくる、第2引数のsockaddr_in(かな?)の内容まで一緒なのか
知りたいかも。

つーか、スレッド使うならソケットをnonblocking modeにしなくていいと思うんだけど、
blocking mode使わない理由があるのかな。
900891:2006/07/19(水) 22:58:10
すいません。単純化したプログラムを1から作りなおして Fedora Core 5
(Kernel 2.6.17-1.2145_FC5, gcc 4.1.1) でやってみたらちゃんと違うファイル
ディスクリプタを返して来ました。

ということで、これは単純に私のプログラムのバグの可能性も出てきました。
申し訳ありませんが明日プログラムを確認してみます。(今手元になくて確認
できないため)。

おさがわせしました。ということでまた明日。

>>899
Nonblocking にした理由は元のプログラムがシグナルを別スレッドで受けていて、
それによってフラグを変更してループを抜けるということをしていたので停止
させたくなかったということです。そういうのがなければ block しても同じですね。
901名無しさん@お腹いっぱい。:2006/07/20(木) 03:08:57
>>900
プログラム板の方にもフィードバックお願いします。
902891:2006/07/20(木) 16:01:45
申し訳ありません。私がバグっておりました。

accept() 後の処理を別関数でやっていたのですが、その中で
fdopen() を使って accept() で受け取ったファイルディスク
リプタから FILE * を作って fgets() や fprintf() を使って
いました。それでその関数から返る直前に fclose() をして
いますが、そうすると当然元となったソケットも close()
されます。

このことをすっかり忘れていたためこの別関数から戻って
来ても accept() で取ったファイルディスクリプタは
オープンしたままだと思い込み、別関数から帰って来てから
close() までの間に別スレッドで accept() した時の
ファイルディスクリプタと同じ値になることがあったため、
今回の疑問に繋がっていました。

ということでお騒がせしました。
Linux でも複数スレッドからの accept() は問題無くできます。
903891:2006/07/20(木) 16:02:16
>>901
書いておきます。
904    :2006/07/21(金) 21:15:16
またまたご冗談を(AA略
905名無しさん@お腹いっぱい。:2006/08/11(金) 02:26:30
>>902
亀レスな上に蛇足かもしれないけど、環境によって同時Acceptは挙動が
違うらしいから排他したほうがいいと何かで呼んだ。
906名無しさん@お腹いっぱい。:2006/08/15(火) 19:11:59
http://www.amazon.co.jp/gp/product/4900900664/ref=sr_11_1/250-8960565-6788252?ie=UTF8

pthreadsの入門書として、これはどうでしょうか?
オライリーだから難しすぎたり、訳が悪かったりしますかね?
907名無しさん@お腹いっぱい。:2006/08/16(水) 01:24:51
悪くないけどちょっと古い。
908名無しさん@お腹いっぱい。:2006/08/16(水) 10:31:03
別に古くはないけど、
銀行ATMの例に沿って進む例題形式だから、
それだけじゃ細かいことまでは分からないね。
それを通読した後、

David R. Butenhof "Programming With Posix Threads" (翻訳が出てるが酷いらしい)
スティーブ・クライマン「実践マルチスレッドプログラミング」
ビル・ルイス「Pスレッドプログラミング」
ダグ・リー「Javaスレッドプログラミング−並列オブジェクト指向プログラミングの設計原理」

辺りを読めば?

Java関係ないじゃんと思うかもしれないが、
この本が優れていることは読めば分かる。
pthreadでしかプログラミングしなくても、
設計面の話なので大いに参考になる。
909名無しさん@お腹いっぱい。:2006/08/16(水) 10:37:17
>>907
>>908
レスありがとうございます。
何も知らないのでとりあえず読んでみます。
910名無しさん@お腹いっぱい。:2006/08/16(水) 12:51:29
W.Richard Stevensの
UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI
http://www.amazon.co.jp/gp/product/4894712059

は高いけど買って損はないと思う。
911名無しさん@お腹いっぱい。:2006/08/16(水) 13:22:22
>>910
それは立ち読みして自分にはまだ難しかったので買ってないです
912名無しさん@お腹いっぱい。:2006/08/16(水) 16:23:57
>>910
キューや共有メモリなどのプロセス間通信の勉強に<Vol.2>は良いですか?
913名無しさん@お腹いっぱい。:2006/08/16(水) 16:32:04
>>908
スティーブ・クライマン「実践マルチスレッドプログラミング」
これは入門者の一冊目として適してますか?

ビル・ルイス「Pスレッドプログラミング」
は廃刊でした。
914名無しさん@お腹いっぱい。:2006/08/27(日) 14:20:14
>>908に挙げたのは、
「通読した後」と書いたように入門用じゃないよ。
入門は>>906でいいんじゃない?

けど読めると思えば、一冊目に、
> スティーブ・クライマン「実践マルチスレッドプログラミング」
でいいと思うけど、pthreadの細かい仕様は、マニュアルを読むことになる。
これは急所どころだけ書いてある。他のスレッドと比べたりして。
915名無しさん@お腹いっぱい。:2006/08/27(日) 14:25:40
とりあえず>>906が分かりやすそうだったので買いました。
これでできるところまで覚えてからクライマンのを読んで見ます。
916名無しさん@お腹いっぱい。:2006/08/29(火) 22:40:43
>>911
や、例にあがっているコードをほぼそのまま使っても動く
ものができてしまう上に、OSの違いによる挙動の違いや、コード
そのものの解説が付いているから、難しいというよりは身体で覚える
タイプの本だ、と個人的には思っている。

>>912
Vol.2は残念ながらあまり見ていない。必要な人には良いとは思うが。
917名無しさん@お腹いっぱい。:2006/09/07(木) 13:25:27
マルチスレッドのプロセスでforkするのって色々難しいですわあ
918名無しさん@お腹いっぱい。:2006/09/07(木) 21:19:34
するな、が正解。fork&execならともかく。
919名無しさん@お腹いっぱい。:2006/09/08(金) 08:22:13
スレッドを作ってからfork&execするのがやっかいなんだあ
920名無しさん@お腹いっぱい。:2006/09/08(金) 17:46:35
プチfork爆弾期待age
921名無しさん@お腹いっぱい。:2006/09/10(日) 18:58:51
質問です。

プロセス内のスレッドはグローバル変数を共有してますが、pthread_createの
最後の引数で渡した変数しかスレッドのルーチンでは読み書きできないんですか?
それとも引数で渡さなくてもグローバル変数はアクセスできるのでしょうか?
922名無しさん@お腹いっぱい。:2006/09/10(日) 19:09:47
自己解決しました。引数で渡さなくてもアクセスできました。
なぜ、ポインタ引数を一つ渡せるような仕様になってるのでしょうか?
必要ないと思うのですが。
923名無しさん@お腹いっぱい。:2006/09/10(日) 19:22:18
スレッドが複数あったら?
924名無しさん@お腹いっぱい。:2006/09/10(日) 19:26:23
>>923
複数あってもすべてのスレッドからグローバル変数はアクセスできるので、
わざわざ引数を設ける必要が無いような気がします。。
知識たらなくてすみません。
925名無しさん@お腹いっぱい。:2006/09/10(日) 19:39:19
( ゚д゚)ポカーン
926名無しさん@お腹いっぱい。:2006/09/10(日) 19:48:47
>>924
知ってる人なら、「スレッドとは」と小一時間話したいけど、
知らない人だと、どんな知識をどれだけ持ってるか分からないから、困る。
927名無しさん@お腹いっぱい。:2006/09/10(日) 19:51:49
>>926
ご教示お願いします、ぜひとも。
入門書は読みました。
928名無しさん@お腹いっぱい。:2006/09/10(日) 20:08:43
>>927
お前の氏素性がわからなきゃ無理って書いてるのに
教えてくれって言うのは、変じゃねーの。

住所氏名性別、学歴、職歴、毎日考えてる事、全部晒してくれたら
ニヤニヤする。
929名無しさん@お腹いっぱい。:2006/09/10(日) 20:10:43
>>928
いやいや、会社で聞くんでいいです。
930名無しさん@お腹いっぱい。:2006/09/10(日) 20:11:43
2ちゃんはカスの集まりなんで、まともに解説できる奴あいねーよ
931名無しさん@お腹いっぱい。:2006/09/10(日) 20:12:38
といえば教えてもらえると思ってもムダです
932名無しさん@お腹いっぱい。:2006/09/10(日) 20:16:02
>>922
深遠な理由があるわけではない。
あった方がグローバル変数だの条件変数だのを使わなくて済む場合が多いから。
でも、こう書くと次は>>800をやらかすだろうから、
とりあえずmallocしたポインタを渡すクセを付けておけ。
933名無しさん@お腹いっぱい。:2006/09/10(日) 20:43:23
>>932
ご教示ありがとうございます。
いろいろ考えられてそうなってるわけですね。
934名無しさん@お腹いっぱい。:2006/09/10(日) 21:42:33
>>922
オブジェクト指向言語(たとえばJava)でスレッドを扱う場合は
大体こんな感じになる。

public class Work implements Runnable {
private String name;
public Work(String name) {
this.name = name;
}
public void run() {
System.out.println("My name is " + name + ".");
}
public static void main(String[] args) {
Work work1 = new Work("Tom");
Work work2 = new Work("Mark");

new Thread(work1).start();
new Thread(work2).start();
}
}

このように、スレッドのエントリポイント(runメソッド)は同じでも、
処理を行うインスタンスが異なっている(work1とwork2)ために、
それぞれのスレッドが別々の処理を行うことができる。

で、pthread APIでも同様に、スレッドのエントリポイント(pthread_createの第3引数)
のほかに、スレッド処理の主体となるデータ(すなわちOOで言う「オブジェクト」)への
参照を渡せるようにしている(pthread_createの第4引数)というわけだ。

コールバック系のAPIをはじめとして、こういう任意のポインタを渡せるようように
なっているAPIは多いが、これらも処理の主体となるデータの受渡しに用いられ、
"opaque pointer"などと呼ばれる。
935名無しさん@お腹いっぱい。:2006/09/11(月) 08:27:09
>>934
なるほど。あえてopaqueなポインタになってるけれども、C++などでは
オブジェクトの参照渡しなど重要になってくるんですね。
ありがとうございました。
936名無しさん@お腹いっぱい。:2006/09/11(月) 11:35:18
・・・
937名無しさん@お腹いっぱい。:2006/09/11(月) 11:59:24
・−・
938名無しさん@お腹いっぱい。:2006/09/11(月) 22:32:32
いやいや、グローバル変数で頑張ろうよ
939名無しさん@お腹いっぱい。:2006/09/12(火) 00:41:08
>>935 は会社で先輩に教えてもらう時に、
途中で生悟りしないでちゃんと不明点が無くなるまで
聞けよ? でないと、迷惑掛けるぞ
940名無しさん@お腹いっぱい。:2006/09/12(火) 10:55:30
量産型バグ 対 シャア専用バグ
941名無しさん@お腹いっぱい。:2006/09/13(水) 07:29:38
グローバル変数でも、読むだけなら良いじゃん。
942名無しさん@お腹いっぱい。:2006/09/16(土) 17:56:26
volatileつければ排他も要らないしw
943名無しさん@お腹いっぱい。:2006/09/16(土) 19:32:54
volatile厨は巣にカエレ!!
http://pc8.2ch.net/test/read.cgi/tech/1157814833/
944名無しさん@お腹いっぱい。:2006/09/24(日) 19:23:28
volatileで排他できるわけないしw
945初心者 :2006/10/27(金) 22:08:21
スレッドを無限ループにしたままで、mainを終了させたらリソースは解放されないで
残るのですか?その場合detached属性つけてスレッド生成すればよい?
946名無しさん@お腹いっぱい。:2006/10/28(土) 00:01:13
>>945
いよいよFreeBSDもm:nスレッドを捨てる日が近付いてきたようだ。
ttp://docs.freebsd.org/cgi/mid.cgi?200610262142.k9QLgNoP035966
947946:2006/10/28(土) 00:02:39
# アンカミスった。無視してくれ
948混沌:2006/10/28(土) 03:50:29
そろそろ1000レスだな〜〜
949名無しさん@お腹いっぱい。:2006/10/28(土) 04:37:11
捨てると決まったわけじゃないよ。
950945:2006/10/28(土) 08:06:02
>>945
誰か答えろや ごっつ困ってんねん
951名無しさん@お腹いっぱい。:2006/10/28(土) 09:52:43
>>945
プロセスが終了したとき、そのプロセスが所有するリソースは全て
OS側に返される。
この原則はマルチスレッドで動作しているプロセスでも同じ。
952名無しさん@お腹いっぱい。:2006/10/29(日) 08:26:55
>>951
ありがたや〜

同期を取る必要の無いスレッド同士だからデタッチにすべきだと思った。
デタッチするとスレッドの戻り値とかをOSが管理しなくていいから少し
は効率よくなるはず?ジョイナブルでも正常にリソースが解放されるのなら、
そもそもデタッチスレッドって何のためにあるの?
953名無しさん@お腹いっぱい。:2006/10/29(日) 08:48:48
joinするのも只じゃないってことじゃね?
954名無しさん@お腹いっぱい。:2006/10/29(日) 14:05:29
>>952
 デタッチなスレッドを使用する意味・・(私の場合です)

 やっぱり、同期は必要になります!?。例えば親子関係のスレッドで、
 子供)処理を終えると親に通知する。(mutexと条件変数を使って)
 親 )通知を受けるが常時待機はしていない。(別な処理をしている)
 こんな関係だと、もし親がjoinで待ってると別な処理が出来ない。この
 待機時間がロスタイムになる。
 最後に親が死ぬ時は、子供状態を記す管理簿の内容で、
 待機するか、即死ねる判断ができる。

 これを、ある社会生活をモデルにすると・・・
 2時間飲み放題(バイキング)とします。
 店側(親)、客(子)にします。
 客)自由に飲み食いします。(酔っぱらって時間の事忘れるかもしれません)
 店)客の利用時間を監視しつつ、料理の準備や雑用をします。
   そして、2時間経過したら 客に帰れ[pthread_kill(客、強制(9))]を
   通知します。もちろん、2時間以内に帰ってくれる客もいます。
  # 客の意志を尊重しjoinで待ってると、経営が成り立ちません。ってか?



 
 
955名無しさん@お腹いっぱい。:2006/10/29(日) 17:14:09
>>953
>>954
大作やなあ

つまり第一にjoinはブロックされるから使用したくない。
でも、親子関係のスレッドで>>954のような処理をする場合でも
あえてデタッチスレッドにしなければならないのだろうか?という疑問が沸いた
ジョイナブルなままでもいい気がするんだけど、。

まあ精進しますわ 
956名無しさん@お腹いっぱい。:2006/10/29(日) 20:20:03
>>955
 954です。
 要求に合った動作ができれば、それでいいと思います。
 しかし、コストパフォーマンスを考慮すると
 そうも行かない場合があります。
 
 joinで待つ間、L2キャッシュを占有されてると迷惑な場合も
 あります。待つのもね。
 だから、用途次第だと思います。
  
957名無しさん@お腹いっぱい。:2006/10/30(月) 18:32:39
> joinで待つ間、L2キャッシュを占有されてると迷惑
解る人居る?
958名無しさん@お腹いっぱい。:2006/10/31(火) 01:01:35
>957
まったく.
意味が掴めない.
詳しくお願いします.
959名無しさん@お腹いっぱい。:2006/10/31(火) 01:17:13
>>957-958
そういうときはスルー力を発揮しなきゃ。
960名無しさん@お腹いっぱい。:2006/10/31(火) 02:33:35
まさか
joinで待つ=対象スレッドが終了するのをポーリングして監視
だと思ってるんじゃあるまいか

ごめん、スルーできなかった
961名無しさん@お腹いっぱい。:2006/10/31(火) 22:43:00
「スルー力」って書き込み自体をしないのが本質だと思います。
何かの記事を真に受けた伝道師みたいに思えます。

>>960
 そのポーリングは無意味で、joinの方がましですよね。

・・・
スレッドに対して、要求する処理が終了して〜スレッド消滅までの時間
正確に測る方法が知りたいんですが、だれか知りませんか?


 


962名無しさん@お腹いっぱい。:2006/11/01(水) 00:30:51
> joinで待つ間、L2キャッシュを占有されてると迷惑

の意味を教えてくれ
>>960 じゃないんだよな?
963名無しさん@お腹いっぱい。:2006/11/02(木) 23:03:12
>>962
 L2キャッシュ・・・
 CPUを基点に、データ保存の媒体として、L1,L2キャッシュ(CPU内部)、
 メモリ、HDD等とあります。
 データへのアクセス時間が最速なのは、前者から順になります。

 そこで、A=A+1 と足し算したい場合、Aはどこに保存されてると
 早く計算できると思いますか?
 
 
 
 
964名無しさん@お腹いっぱい。:2006/11/03(金) 03:20:01
はい、レジスタ!
965名無しさん@お腹いっぱい。:2006/11/03(金) 03:54:08
スルーとしけばよかった(>_<)反省
966名無しさん@お腹いっぱい。:2006/11/03(金) 06:11:44
で?
967名無しさん@お腹いっぱい。:2006/11/03(金) 08:02:55
俺はYahoo!のブリーフケースに保存している。
968名無しさん@お腹いっぱい。:2006/11/03(金) 10:05:43
ブリーフへのアクセス時間が最速、それはブリーフケース
969名無しさん@お腹いっぱい。:2006/11/03(金) 10:18:37
ブリーフケース、ベリーフケース、ベリーファスト!

なるほど
970名無しさん@お腹いっぱい。:2006/11/03(金) 18:03:19
↑笑えるポイントは?
971名無しさん@お腹いっぱい。:2006/11/03(金) 20:33:29
三段活用だろ
972名無しさん@お腹いっぱい。:2006/11/04(土) 00:10:07
↑解説ありがと。

笑えないけど、笑ってあげよう。
973名無しさん@お腹いっぱい。:2006/11/09(木) 15:07:44
>>518>>887>>888
http://lists.freebsd.org/pipermail/freebsd-threads/2006-October/003771.html
読むと対抗意識持ちつつ仲よくやってるみたいね。
974名無しさん@お腹いっぱい。:2006/12/12(火) 02:40:09
以下は、sem_wait/sem_post を使って同時に 2 スレッドまでしか
走行できないように排他処理を行うテストコード。
これを linux の gdb(6.4.90 系) で実行すると、なぜか assert に
引っかかってしまいます・・・。
debian etch でダメ。なぜか vine4.0 だと問題なし。

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX_THREAD_NUM (2)
#define THREAD_NUM (8)
sem_t sem;
void thread_func(void *arg) {
int id = (int)arg;
int ret = sem_wait(&sem);
assert( ret == 0 );/* gdb だと謎エラー */
printf("%d start.\n", id);
sleep(1);
printf("%d finish.\n", id);
sem_post(&sem);
}
int main() {
int i;
pthread_t handle[THREAD_NUM];
sem_init(&sem, 0, MAX_THREAD_NUM);
for (i = 0; i < THREAD_NUM; ++i){ pthread_create(&handle[i], NULL, (void *)thread_func, (void *)i); }
for (i = 0; i < THREAD_NUM; ++i){ pthread_join(handle[i], NULL); }
sem_destroy(&sem);
return 0;
}
975974:2006/12/12(火) 02:55:22
debian etch 、vine4.0 ともに gdb のバージョンは 6.4.90。
ということは libc のバージョンの差が原因なのか・・・。
なんにせよ、gdb 上でセマフォがさっぱり機能しないというのは
つらいです。
976名無しさん@お腹いっぱい。:2006/12/12(火) 08:12:05
謎つうかerrnoは見ないの?
977名無しさん@お腹いっぱい。:2006/12/12(火) 08:51:37
sem_initの戻り値をまず確認しないと。
978名無しさん@お腹いっぱい。:2006/12/12(火) 12:57:25
>>974
これが原因じゃないような気はするけど、念のため、
sleep(1)使うのやめてpoll(NULL, 0, 1000)にしてみたら?

あとは>>976に同意。
979名無しさん@お腹いっぱい。:2006/12/12(火) 13:08:45
「あとは」じゃなくて、まずerrno。
980名無しさん@お腹いっぱい。:2006/12/12(火) 13:47:09
細かい日本語のつっこみくらいしかできない人乙
981974:2006/12/13(水) 01:31:19
sem_init() の戻り値は 0(=正常終了)です。
sem_wait() の戻り値は 4(=EINTR)でした。

回避方法が判明しました。
sem_wait() が EINTR で失敗した場合 while ループで
リトライする仕掛けにすると良いようです。
982名無しさん@お腹いっぱい。:2006/12/13(水) 03:35:57
Wait中になにかSignal来てんだろ。つか普通するだろEINTR対策
983名無しさん@お腹いっぱい。:2006/12/13(水) 09:18:19
SIGTRAPとか
984名無しさん@お腹いっぱい。:2006/12/14(木) 01:09:44
>>980
エラー処理もせずに、>>978の前半のような試行錯誤を繰り返すのは愚の骨頂。
985名無しさん@お腹いっぱい。:2006/12/14(木) 04:48:49
write()でエラー確認せず文句言うヒトもいます
986名無しさん@お腹いっぱい。:2006/12/14(木) 07:07:49
全てのsystemcallにEINTRチェックを入れるのはしんどい。
987名無しさん@お腹いっぱい。:2006/12/14(木) 14:40:33
>>980
>>984
あれって単なるサンプルコードじゃないの?どうでもいいけど。
サンプルコードに必死になるのはばかばかしいと思って。
988名無しさん@お腹いっぱい。:2006/12/17(日) 17:04:02
writeしながらwriteしたいんですけど、誰がwriteですか?
989名無しさん@お腹いっぱい。:2006/12/20(水) 09:55:38
埋め
990名無しさん@お腹いっぱい。:2006/12/20(水) 10:35:04
お尻がウンコ臭い
991名無しさん@お腹いっぱい。:2006/12/20(水) 11:40:41
次スレは立てますか?
992名無しさん@お腹いっぱい。:2006/12/20(水) 11:57:49
いらないよ。
やるならここで。

マルチスレッドプログラミング相談室 その5
http://pc8.2ch.net/test/read.cgi/tech/1157814833/
993名無しさん@お腹いっぱい。:2006/12/20(水) 12:42:32
埋めないと立てますよ
994名無しさん@お腹いっぱい。:2006/12/20(水) 13:25:49
UNIX板に一つくらいpthreadのスレがあってもいいんじゃないかしらん?
無理に他に集約する必要もないでしょう。
995名無しさん@お腹いっぱい。:2006/12/20(水) 13:47:18
無理に分散する必要もないよ。
996名無しさん@お腹いっぱい。:2006/12/20(水) 13:58:08
分散は嫌だ
997名無しさん@お腹いっぱい。:2006/12/20(水) 22:17:15
998名無しさん@お腹いっぱい。:2006/12/21(木) 15:23:19
999名無しさん@お腹いっぱい。:2006/12/21(木) 17:59:53
1000名無しさん@お腹いっぱい。:2006/12/21(木) 18:00:37
遂に念願の1000GET
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。