マルチスレッドプログラミング相談室 その4at TECH
マルチスレッドプログラミング相談室 その4 - 暇つぶし2ch369:デフォルトの名無しさん
06/03/05 00:20:02
>>364 例の URLリンク(www.nwcpp.org)
の最後のほうに
> Replace global singletons with per-thread singletons:
> - Each can use thread-local storage.
> -- Threading concerns during initialization thus vanish.
> - But now there are multiple "singletons."
と書いてあって、TLSを364のようには使ってないのが気になります。

一方、
URLリンク(www.cs.umd.edu)
でDoug Leaさんが364方式のTLSの使い方に文句を言っていない(条件
付きながら)ので大丈夫な気もします。まぁ、かなり昔のML投稿ですけど
ね・・。

さて真相は?

370:デフォルトの名無しさん
06/03/06 16:07:01
>>340
普通の卵は比較的簡単に立つよな。表面に凹凸があるから。産みたてほど立ち易い。
・・・コロンブスは卵をツルツルに磨き上げていたに違いない。

371:デフォルトの名無しさん
06/03/06 17:35:06
>>370
まあまあ。
コロンブスもギャグで言っただけなんだから許してやってくれ。

372:デフォルトの名無しさん
06/03/06 19:33:03
後世の作り話ですから。
まあ>>340は底抜けの馬鹿だけど。

373:デフォルトの名無しさん
06/03/07 14:35:11
ゆで卵にして高速で回せば立つよ。
まあ>>372は底抜けの馬鹿だけど。

374:デフォルトの名無しさん
06/03/07 14:57:53
盛り上がっているところ、横から突っ込んでスマンけど。

生卵を立てるには塩をごく少量盛って、その上に立てて、横から
息をゆっくり吹きかけて塩を飛ばすといいという話を聞いた。

とかいう本当にどうでもいい話をマルチスレッドスレでする
自分は底抜けの馬鹿ですw


375:デフォルトの名無しさん
06/03/07 19:27:05
つまり塩スレッドに卵スレッドをロックさせれば桶?

376:デフォルトの名無しさん
06/03/08 10:03:12
卵スレッド発見

377:デフォルトの名無しさん
06/03/08 20:55:31
つまらんよ >>369-376

378:デフォルトの名無しさん
06/03/08 21:34:40
君ほどでも

379:デフォルトの名無しさん
06/03/08 23:26:59
ゆで卵の殻を剥かずに塩をかけるなんて、底ぬけの馬鹿ですね

380:デフォルトの名無しさん
06/03/09 03:03:29
観光地のゆで卵は全部そうなってるよ

381:デフォルトの名無しさん
06/03/09 03:09:09
>>379
卵殻はNa+イオンもCl-イオンも透過するのでちゃんと卵に塩味がつきます。
溶けさえすれば。

382:デフォルトの名無しさん
06/03/09 15:12:11
※注意: このスレはこの卵ネタで1000まで引っ張る覚悟です

383:デフォルトの名無しさん
06/03/09 15:22:01
たまごが立つという状態を定義してください。

384:デフォルトの名無しさん
06/03/09 16:21:34
ブスの卵

385:デフォルトの名無しさん
06/03/09 17:20:48
>>383
案1:
水平方向の任意の角度から卵を投影したときに、水平方向のスパンよりも鉛直方向のスパンの方が長い状態。
ただし卵が他の物体と接することができるのは下部のごくせまい部分のみとする(←うまい定義できないなこれ)

386:デフォルトの名無しさん
06/03/09 20:48:52
ポテンシャルの極大点。

387:デフォルトの名無しさん
06/03/09 21:13:15
あ、あんたなんかにたたれてもうれしくないんだからねっ!

388:デフォルトの名無しさん
06/03/10 00:28:56
>>383
おまいはコンピュータか? んなもん定義しないでも分かるだろ

389:デフォルトの名無しさん
06/03/10 03:03:47
クララが立った、と言う状態を定義してください。


390:デフォルトの名無しさん
06/03/10 03:04:39
精神的な自立

391:デフォルトの名無しさん
06/03/10 03:21:15
それで泣ける、という状態を定義してください。

392:デフォルトの名無しさん
06/03/10 08:40:40
クララが勃った、と言う状態を定義してください。

393:デフォルトの名無しさん
06/03/11 18:55:33
クララが勃った
クララは女である
∴よって勃ったのは乳首である

394:デフォルトの名無しさん
06/03/11 19:03:44
class clitoris extends electiliable {

395:デフォルトの名無しさん
06/03/12 11:42:52
>>394
なんだ、選挙にでも出るんか?













…それを言うならerectibleだろ。

396:デフォルトの名無しさん
06/03/12 16:25:47
Win32
Administrator権限で実行されてるプロセスからスレッドを起こすとき、
スレッドそれぞれに異なるユーザー権限を設定することは可能?
プロセスごとならできるんだが。もし可能ならAPI名などヒントを頼む。

397:デフォルトの名無しさん
06/03/12 16:54:30
インパーソネーションとかいうんだっけ?
ImpersonateLoggedOnUserとか。
まー、RevertToSelfとか呼ばれると、元に戻るけどね。

398:デフォルトの名無しさん
06/03/12 21:06:38
>>397
ありが㌧。
まだ試せてないが、MSDNの説明から目的に適うAPIのよう。

399:デフォルトの名無しさん
06/03/15 14:41:37
なぁなぁ、
class Job extends Thread {
     public void run() {}
}

class MyJob extends Job {
     public void run() {}
}
ってあったらMyJobのrun()がJobのrun()をオーバーライドするんで
Jobのrun()に書いてある定義とか全部無視されちゃうよね?
ちゅーか、Jobのrun()の一行目に
System.out.println("Hello? Hello? Can you read me?");//never displayed
と書いても表示されないから間違いない。
でも、どうやったら両方のrun()とも動かすこと出来るんだろ?

400:デフォルトの名無しさん
06/03/15 14:42:42
一応ageとく。

401:デフォルトの名無しさん
06/03/15 14:54:45
>>399
1つのスレッドで順番に動かしたいのか?
MyJob.run() と Job.run() を別のスレッドで動かしたいのか?
MyJob と Job のインスタンスをそれぞれ作ったらいけないのか?



402:デフォルトの名無しさん
06/03/15 15:48:21
>>401
ありがと。
二番目の「別のスレッドで動かしたい」かな。
run()直接アクセスするとあかんのよね、.startで始めないと?
どうしようかな?

403:デフォルトの名無しさん
06/03/15 16:35:55
>>402
その手法が可能かどうかの前に、やろうとしていることに対して
もっと単純な方法や、別の解法が無いか検討したらいいんじゃ
ないかな。

ちょっと言語(Java?)の使い方から外れているみたいので、
本当にやりたいことが妥当かどうか見極めた方がいいと思う。

404:デフォルトの名無しさん
06/03/15 22:37:56
>>399
super.run();

405:デフォルトの名無しさん
06/03/16 09:59:17
>>403
確かにそうだったかもしれん。ありがと。

>>404
いや、直接run()にアクセスするのは禁(ry

406:デフォルトの名無しさん
06/03/16 14:36:26
Linux  2.4.31-0vl1.8smp + glibc-2.3.3-3vl1.3

pthread (linuxthread) プログラムでたまーに(でも確実に) seg fault してしまいます。
該当箇所は
 pthread_mutex_unlock(&mutex_sleep);
という処理で、mutex_sleep はグローバル。core dump に聞いてみたらこんな返事が。

Program terminated with signal 11, Segmentation fault.
#0  0x080551c7 in __pthread_alt_unlock (lock=0x80cb548) at spinlock.c:600
      } else if ((prio = p_node->thr->p_priority) >= maxprio) {
(gdb) bt
#0  0x080551c7 in __pthread_alt_unlock (lock=0x80cb548) at spinlock.c:600
#1  0x08051fc9 in __pthread_mutex_unlock (mutex=0x80cb538) at mutex.c:199
#2  0x0804e3cc in send_proc (arg=0xc) at send_proc.c:112
#3  0x08051709 in pthread_start_thread (arg=0xbdbffbe0) at manager.c:309

何か情報ありますか?

407:デフォルトの名無しさん
06/03/16 20:44:16
mutexがすでに死んでるとか?

408:デフォルトの名無しさん
06/03/16 22:30:14
Windows Threadについて質問です。擬似コードですが、
Thread[] threads = getAllThread();
foreach (Thread t; threads) {
t.suspend();
}
このような全てのスレッドを止めるためのループがあるとします。
このループ中では、既に止められているスレッドと、
これから止められる予定のスレッドがあると思うのですが、
これから止められる予定スレッドが、既に止めたスレッドを再開(resume)するため、
このループでは全てのスレッドを止められない、ということは起こりえるのでしょうか?


409:デフォルトの名無しさん
06/03/16 22:36:16
>>408
起こりうるでしょうね。
避けたいのならばまず自分の優先順位をトテモ高くして、
その後ループに入れば良いと思います。

先方のスレッドも優先順位を上げている恐れがあるのならば
完全ではありませんが。

410:デフォルトの名無しさん
06/03/16 22:36:36
知らね。

だって、普通そんな造りにしないもん。
普通は、終了しろ、っていう合図を各スレッドに送って
自主的に終了なり中断なりするのを待つだけだから。

411:デフォルトの名無しさん
06/03/16 22:37:03
起こりえる。
おまけにこれから止めようとするスレッドが新たにスレッドを作るかもしれない。
全スレッドで、「スレッドマネージ用ミューテックス」などを使用すればいいんでない?

412:デフォルトの名無しさん
06/03/16 22:39:04
他のスレッドを suspend するってのはまず間違いなく設計ミス。
C のランタイムとか Windows に用意されているいろんな dll の
内部まで良く知っていて、何か大事なものの所有権を持ったまま
suspend されちゃったりすることはないと確信を持っているなら
別だけど。

413:408
06/03/16 22:46:12
どうも。
実は、これのpause版とresume版がD言語の標準ライブラリの中にあって、
GCを呼ぶ前にそれでスレッド止めて、後に再開ようとしているみたいなのですけど、
それのへんでアプリケーション側で実装しているスレッドの同期が変になるみたいです。
安心できませんが、安心しました。


414:408
06/03/16 22:52:58
スレッドを止める仕様はどうしようもないのですが、
とりあえずは、全てを止めるループ中(pauseAll)に
pause()、resume()とstart()が実行されないように排他とと
全てを再開(resumeAll)中に、resume()が実行されないように
排他したら大丈夫ということでしょうか?


415:デフォルトの名無しさん
06/03/16 23:01:54
>>414
GC 側が単純なメモリ操作などだけで、
他の処理で使っている(かもしれない)セマフォやミューテックスなどの
所有権なしで実行できるとするなら、問題ないはず。

例えば(MSのドキュメントを信用するなら)Windows API の OutputDebugString は、
内部で他のスレッドを全て Suspend した上でデバッグメッセージの送信を行い、
そののち Resume する、と同様の処理を行っているようです。

AP側のスレッドが変になるのはAP(or Dの何か他のライブラリ)のバグではないでしょうか。

416:408
06/03/16 23:28:41
>>415
resumeThreadの戻りを見ながら、他スレッドのsuspend待ちをしている箇所があるので、
それが、排他されていないresumeAll中に走ると、
GCが止めてこれから再開する予定のスレッドを、
"アプリケーションが思っている理由"でsuspendしたのだと
勘違いして変になるのだと思っています。


417:デフォルトの名無しさん
06/03/17 06:51:35
>>407
ありがとうございます。
pthread_mutex_destroy は呼んでいないので生きていると思っていたのですが、どうやら
syslog(3) が関係しているようです。別の core dump に聞いてみたら syslog 関数で死んで
いるケースが見つかり、付近の syslog(3) をはずしたら seg fault することはなくなりました。

syslog(3) と pthread (linuxthread) は混ぜるな危険とかいう話があるんでしょうか。
とりあえず syslog を自前で用意することにしてみます。

418:デフォルトの名無しさん
06/03/17 07:20:23
その環境ではsyslog(3)はMT-Safeじゃないのに、排他してないだけとか

419:http://www.vector.co.jp/soft/win95/util/se072729.html
06/03/18 19:49:50
TextSS のWindowsXP(Professional)64bit化おながいします

もしくは64bitにネイティブ対応したテキスト置換ソフトありますか?



420:デフォルトの名無しさん
06/03/28 00:13:15
こんな問題助けてください。
I/Oバウンドな処理をする処理プログラムが2個
CPUバウンドな処理をするプログラムが1個

それぞれCPUは85~95%占有するほど負荷が大きいです。
またそれぞれI/O処理は多重スレッドはなく2つの独立した
スレッドプログラムです。

Xeon 64bit x2 (64bitSMPカーネル+ HTTでCPU4個)
Xeon 32bit x2 (32bitSMPカーネル+ HTTでCPU4個)

Opteron 252 x 4(64bitSMPカーネル)
Opteron 252 x 4(32bitSMPカーネル)

いずれの場合も、CPUを占有したいと考えるならばcpu_affinityを
ハードウェア的に割り当てるべきなのでしょうか。
それともカーネルのSMP処理に任せるべきなのでしょうか。

421:デフォルトの名無しさん
06/03/28 06:09:38
page outないくらいメモリが十分にあると考えると、
(OSによってはI/Oキャッシュがメモリを食い潰してしまいますが)
I/Oバウンドな処理をするプログラムにCPU割り当てる意味ないでしょ。

けど、
> それぞれCPUは85~95%占有するほど負荷が大きいです。
で「I/Oバウンド」なの?

それからマルチスレッドじゃないw

422:デフォルトの名無しさん
06/03/28 12:47:04
>>420
CPU占有を占有したいなら、邪魔しに来る恐れのあるほかのプロセスは
どれか他のCPUに割り当てるべき。

CPUを占有することの利点は、
・他のCPUでの処理の邪魔をしない
・各CPUが独立した2次キャッシュを持っているとき、キャッシュの汚染に
よるパフォーマンス低下を避けられる(かもしれない)
の2つくらい。

カーネルに任せるべきかどうかはなんともいえない。
プログラムの性格にもよるし、カーネルのスケジューラーの実装にもよる。

423:420ではない
06/03/29 00:15:05
ぶっちゃけ聞きたいんだが、
「cpu_affinityをハードウェア的に割り当てる」
って、現在存在するOSの中でどれよ?

424:デフォルトの名無しさん
06/04/04 15:54:42
C++で質問ぬ
beginthreadexで作ったスレッド
exitthreadexしないで スレッド関数return で終了して
CloseHandleしても問題ないですか?

サンプルで exitthreadをreturn の前に呼んでるのと
呼んでないの
があったので



425:デフォルトの名無しさん
06/04/04 16:29:21
>>424
寧ろ、exitthreadするとC++のデストラクタが走らないので問題になりがち。
極力returnするべき。

426:デフォルトの名無しさん
06/04/06 01:56:06
世はSPEでプログラミングしたいのじゃ

427:デフォルトの名無しさん
06/04/06 13:02:49
>>423
つ z/OS

428:デフォルトの名無しさん
06/04/16 00:01:57
世界で始めてデッドロックを実際に経験した人って誰だろう。
あまりにもの恐ろしさに震え上がったことだろう。

429:デフォルトの名無しさん
06/05/06 21:33:59


430:デフォルトの名無しさん
06/05/06 22:23:42
哲学者よフォークを取れ!!

431:デフォルトの名無しさん
06/05/06 23:33:04
先生、フォークが足りません!!

432:デフォルトの名無しさん
06/05/06 23:41:15
フォークを取ってどうすんだよw

433:デフォルトの名無しさん
06/05/06 23:46:41
通じてないのかさらに深い洞察なのか…


434:デフォルトの名無しさん
06/05/06 23:47:34
そうかパスタを取れか!!


435:デフォルトの名無しさん
06/05/06 23:50:03
>>434
てめー、すました顔してないで早くフォークよこせよ

436:デフォルトの名無しさん
06/05/06 23:54:39
まず全てのフォークをいったんテーブルに戻して、
そして...



















哲学者よフォークを取れ!!

437:デフォルトの名無しさん
06/05/06 23:55:20
すまん、記憶違いだったら悪いんだが。
哲学者よときたら「箸をとれ」じゃなかったか?

438:デフォルトの名無しさん
06/05/06 23:58:02
>>432
哲学者の食事問題を知らない奴キター

439:デフォルトの名無しさん
06/05/06 23:59:11
>>437
ヒント:哲学者は日本人ではない

440:デフォルトの名無しさん
06/05/07 00:00:54
ヒント:ダイクストラ

441:デフォルトの名無しさん
06/05/07 00:10:23
哲学者よ

死ぬくらいなら手づかみで食え


442:デフォルトの名無しさん
06/05/07 00:11:25
哲学者はきわめて明確な論理で行動するため、
臨機応変などという言葉は通用しません。


443:デフォルトの名無しさん
06/05/07 00:17:27
哲学者は、野蛮では無く極めて理知的に出来ております。

444:デフォルトの名無しさん
06/05/07 01:26:53
Dining Philosophers Problem は設定がシュール過ぎて
授業中に笑い出しそうになった

445:デフォルトの名無しさん
06/05/07 04:53:31
シュレディンガーが猫を題材にしたのと通じるものがあるな

446:デフォルトの名無しさん
06/05/07 09:56:09
お前なーやめろよ
話の流れから

シュレディンガーが猫を食材にしたのと通じるものがあるな

と読んじゃったじゃないか
まぁ、たいして違いはないが

447:デフォルトの名無しさん
06/05/07 13:34:52
哲学者よ、明日はパスタにしよう。うん、パスタ。

448:デフォルトの名無しさん
06/05/07 21:18:36
哲学者は手掴みで食べないものなのですか?

449:デフォルトの名無しさん
06/05/07 21:22:19
哲学者はそんなはしたないまねはしません。
しかし決して人に譲ることもしません。


450:デフォルトの名無しさん
06/05/08 00:23:38
哲学者よデスマーチから逃げれ!!

451:デフォルトの名無しさん
06/05/08 09:39:33
age

452:デフォルトの名無しさん
06/05/09 20:31:01
Cでスレッド固有のグローバル変数みたいなものって使えないかな
ほぼ全ての関数でスレッドごとに値の違う変数使ってるんで
毎回引数に加えるのが面倒になってきた

453:デフォルトの名無しさん
06/05/09 20:48:51
処理系固有でTLSなどがあるとは思うが。

454:デフォルトの名無しさん
06/05/09 22:34:47
>>453
サンクス。しらんかった

455:デフォルトの名無しさん
06/05/10 00:58:57
gccだと、

__thread int i;

とか。

456:デフォルトの名無しさん
06/05/10 01:26:42
調べました
pthreadだとpthread_key_create()とかですね
__threadの方が扱いやすいけどポータビリティとしてはどうなんだろう
gcc依存でも別に困りはしないんですけどw
何はともあれありがとうございました~

457:デフォルトの名無しさん
06/05/10 08:23:30
ポータビリティが気になるなら APR とか使うのは?

URLリンク(apr.apache.org)

458:デフォルトの名無しさん
06/05/14 15:00:46
結城浩のデザインパターン スレッド編って買い?

459:デフォルトの名無しさん
06/05/16 12:59:06
   .  -‐-  .  
__ 〃       ヽ :  
:ヽ\ ノノノ)ヘ)、!〉 :
'. l(0_)!。-‐ ‐〈リ .はわわ~マルチが459ゲットですぅ…
 ;Vレリ、" (フ/ ; 
    : l´ヾF'Fl :           ∧__∧____ 
   ;. 〉、_,ノ,ノ :          /|・∀・ ┥ ./\
  . /ゝ/´, ヽヽ . .     /| ̄∪∪ ̄ ̄|\/  
  : く/l |_ノト‐'⌒),) .      |  拾って  |/ 




460:デフォルトの名無しさん
06/05/20 17:07:49
>>458
買い。

461:デフォルトの名無しさん
06/05/22 00:45:49
longの読み書きについて質問失礼します。

①マルチスレッドで InterlockedExchange を使用し、longの値を変更しています。
②別スレッドで①で変更しているlong値を参照しています。
(読むだけの Interlocked~ の関数が見当たらない為)
この処理って大丈夫なんでしょうか?

実際にソースに組み込んでテストしているのですが、今の所大丈夫っぽいです。。。


462:デフォルトの名無しさん
06/05/22 01:19:41
volatile修飾すれば大丈夫という噂

463:デフォルトの名無しさん
06/05/22 01:25:57
共有リソースを元に、あるメモリに書き込みとかをしなければ問題ないよ。
参照だけなら、何の問題もなし。

464:デフォルトの名無しさん
06/05/22 03:01:15
Interlocked.Read

465:デフォルトの名無しさん
06/05/22 03:01:52
てv1か…
Interlocked.Readは2からだったな…


466:デフォルトの名無しさん
06/05/22 06:15:08
>>461
InterlockedExchangeAdd

467:デフォルトの名無しさん
06/05/23 16:38:37
Pentium XE 840 ではHyper-Threading有効となっているので、
デュアルコア×2スレッドで4スレッド同時処理ができますが、
HTの論理コアを判別する方法はないでしょうか?

SetThreadAffinityMask() を利用して1つのコアを
スレッドに対して独占的に割り当てた場合にHT論理コアだと
処理速度向上が余り望めません。

もしくはWindowsでCPU番号(コア番号)が
どのように割り当てられるかご存知ないですか?

単純に↓とか?
CPU1-Core1-Main
CPU1-Core1-HT
CPU1-Core2-Main
CPU1-Core2-HT

Opteron だと?
CPU1-Core1
CPU1-Core2
CPU2-Core1
CPU2-Core2

468:デフォルトの名無しさん
06/05/23 18:35:25
>>467
何か勘違いしてないか?

469:デフォルトの名無しさん
06/05/23 22:13:13
>>468
何か勘違いしてないか?

470:デフォルトの名無しさん
06/05/26 02:28:01
>>467
それはOSの仕事

471:デフォルトの名無しさん
06/05/26 09:01:15
SetThreadAffinityMask(hThread,0x01);
SetThreadAffinityMask(hThread,0x02);
SetThreadAffinityMask(hThread,0x04);
SetThreadAffinityMask(hThread,0x08);
とした時にどのコアが使用されるか知りたいってことじゃねーの?

472:デフォルトの名無しさん
06/05/26 11:26:01
>>467
URLリンク(www.intel.com)

SetThreadAffinityMaskでCPUにスレッドを固定した後、
当該スレッド APIC ID を入手して core id と SMT ID を入手すればよい。

用語が混乱してるようだけど、Coreっていうのはホントのcoreのことで、
コアの中で演算回路等を共有して独立したCPU風に振舞うのはlogical
cpu とか SMT とか言う。

例えばDualCore でコアあたり2つのSMTをサポートするCPUの論理CPU構成は
Core1-SMT1 / Core1-SMT2 / Core2-SMT1 / Core2-SMT2 だ、
とこんな風に言う。

473:デフォルトの名無しさん
06/05/26 12:26:42
CRITICAL_SECTIONを使う場合ローカルなstatic変数として使用してもよいのでしょうか?
↓のような関数をスレッド内で呼び出す場合です。(ここではcountに同時アクセスしないようにすることを目的とする)
int hoge(int init, int del, int i)
{
  static CRITICAL_SECTION cs;
  static int count;

  if(init) InitializeCriticalSection(&cs);
  if(!init && !del)
    {
      EnterCriticalSection(&cs);
      count += i;
      LeaveCriticalSection(&cs);
    }
  if(del) DeleteCriticalSection(&cs);

  return count;
}

474:デフォルトの名無しさん
06/05/26 16:39:43
>>470
ヴァカ発見

475:名無しさん
06/05/26 19:42:14
>473
関数のセマンティクスとしてはクソだが、特に問題は発生しないだろう。

476:467
06/05/26 20:21:43
>>472
なるほど…スレッドを固定してCPUIDでチェックすれば判別できそうですね。
用語解説は非常に勉強になりました。
ありがとうございますー

良く考えてみればSMT1が軽い負荷ならSMT2に重い負荷を
かけても遅くならないのかな…?
だとすると、同じコアのSMT1とSMT2に割り当てないようにすれば
効率が良さそうですね。

477:デフォルトの名無しさん
06/05/26 23:31:44
時期尚早な最適化は諸悪の根源だ

478:473
06/05/27 00:41:46
>>475どもです。

479:デフォルトの名無しさん
06/05/27 01:31:47
>>476
みんなpthreadのデバッグってどうやってやってますか?

1ソースコードから処理を推測してデバッグ
2とりあえずなんでもいいからprintf仕込んでデバッグ
3gdbを利用する
4ツールを使って調査する。
もしいいツールとか方法あれば教えてください。

480:デフォルトの名無しさん
06/05/27 11:05:19
>>479
つ【5 - pthreadの気持ちになってみる。】


481:デフォルトの名無しさん
06/05/27 12:17:16
>>479
pgdbgはどうよ? (というかプラットフォームは何よ?)

Linuxは、IBMがpthreadを手がけた時に、
libpthdebug.aがAIXから持ち込まれるかと思ったが、
IBM版はlinuxサイドから拒絶されたので実現しなかった…

482:デフォルトの名無しさん
06/05/27 12:30:20
pgdbgですかぁ渋いですね
それでいっちょ今から会社飛んでデバッグしてきますね

483:デフォルトの名無しさん
06/05/27 17:23:07
基本的に知識足りてねぇって感じなんですが質問させてください。
boostのmutexとconditionでWindowsAPIのEventと同等機能をやろうと思ってやってたんですが
boost::condition::notify_oneを呼ぶときもmutexでロックしないとまずいですか?
これがデッドロックせずに動くってことは多分そういうものだとは思うのですが…

boost::mutex g_mutex;
boost::condition g_cond;

void Wait()
{
 boost::mutex::scoped_lock lk(g_mutex);
 g_cond.wait(lk);
}

void Notify()
{
 boost::mutex::scoped_lock lk(g_mutex); // これって必要ですか?
 g_cond.notify_one();
}

484:デフォルトの名無しさん
06/05/27 23:06:05
それでええで。
examples/libs/thread/example/condition.cpp 見てみ。

485:デフォルトの名無しさん
06/05/27 23:06:55
examples/は余分やな…

486:デフォルトの名無しさん
06/05/27 23:20:41
だめだ、pthreadが周りでどうしても落ちる
セグ落ちでどうしてもダメううーん発見できん
神様助けてくれ

487:デフォルトの名無しさん
06/05/28 23:20:52
>>484
ありがとうございます、スッキリしました。

488:デフォルトの名無しさん
06/05/30 18:30:41
>>486
落ち始める直前の状態にまで戻して何やったのか胸に手を当てて考えてみれ。


489:デフォルトの名無しさん
06/05/31 00:36:18
ふっふっふっふ私はもうスレッドは怖くない
スレッドの挙動を完璧把握する方法を知ってしまった
ふっふっふっふ

490:
06/06/01 02:46:02
pthread_cond_timedwaitで、指定タイマーを経過しても待ち状態解除されず
停止したままになってしまっているのですが、引数パラメータに問題が
あるのでしょうか。
gdbで確認したところ引数は問題なさげで、pthread_cond_timedwait内の
pthread_sigsuspendで停止してるっぽいのですが…。

491:デフォルトの名無しさん
06/06/01 12:38:26
糞カーネルを使っているに一票

492:デフォルトの名無しさん
06/06/07 01:46:39
まずOSの種類とカーネルの素性晒せ

493:デフォルトの名無しさん
06/06/07 08:46:05
LINUXですよ(^^)

494:デフォルトの名無しさん
06/06/08 01:10:24
それは windows でない。とだけ言ってるに等しい

495:デフォルトの名無しさん
06/06/08 13:42:04
マルチスレッドとマルチプロセスでは一般的にどちらが効率的ですか?

496:デフォルトの名無しさん
06/06/08 18:36:22
タスク間のデータ参照が多いプログラムと少ないプログラムでは、どちらが「一般的」ですか?

497:デフォルトの名無しさん
06/06/10 01:47:28
volatileで回避できますか?

498:デフォルトの名無しさん
06/06/10 04:22:44
volatileとstaticで8割方回避できます!

499:デフォルトの名無しさん
06/06/10 08:47:58
なにをだ。

500:デフォルトの名無しさん
06/06/10 10:14:15
mutexとvolatileでは一般的にどちらが効率的ですか?

501:デフォルトの名無しさん
06/06/10 12:19:02
コーディング効率か
コードの効率か
で回答が変わってくる可能性がある

502:デフォルトの名無しさん
06/06/10 12:24:23
volatileはLockFreeで高速だが、アトミック操作に限定されるので、
一変数ならともかく、全体の整合性がどういう言い出すとプログラムは
とっても面倒だし、バグがあるかないかの検証も面倒くさい

503:デフォルトの名無しさん
06/06/10 12:54:08
( ゚д゚)ポカーン

504:デフォルトの名無しさん
06/06/10 14:14:06
>>501-502 がマジレスである可能性を想像し、背筋が凍った。

505:デフォルトの名無しさん
06/06/10 15:55:27
そのまま風邪引いて肺炎悪化させて死んでくれ

506:デフォルトの名無しさん
06/06/10 16:56:15
こんにちわ。誘導されてきました。
セマフォの扱い方について、よろしければ教えてください。

以下が環境です。
・HP-UX & aCC
・共有メモリを使用し、その排他制御にセマフォを使用している
・共有メモリとセマフォは専用のクラスを作成して管理している
・上記資源は複数のプロセスで使用する
・上記管理クラスのインスタンスはプロセス内に複数存在する

やりたいことは以下の通りです。
・1つのプロセス内で、同じキー値を利用するセマフォの lock を
 ネストさせても2回目以降の lock で固まらないようにしたい
・unlock はネスト中の実際に lock した箇所に対応したところで
 実行するようにしたい

 void a() {               void b() {
  CSemafore sem1;            CSemafore sem2;
  sem1.lock();                sem2.lock(); ←ここで固まらないようにしたい
  b();                     sem2.unlock();
  sem1.unlock(); ←ここで解除したい  }
 }

セマフォのクラスインスタンスが1つの場合は lock の回数を数えるカウンタを
用意することで解決できそうなのですが、複数の(同じキー値を利用する)インスタンスが
絡んできた場合に、上手に処理する方法が思い浮かびません。

こういったことは可能なのでしょうか。ご教示頂けると嬉しく思います。
よろしくお願いいたします。


507:デフォルトの名無しさん
06/06/10 17:01:47
trylockしてみて無理だったら待てばいいんじゃねぇの?
違うってかゴメンね

508:デフォルトの名無しさん
06/06/10 17:27:39
>>506
どういうデッドロックを想定しているの?

th1がaをlockしてbを得ようとして、th2がbをlockしてbを得ようとしているとか?

入れ子セマフォア
多重セマファオ
で解決できませんか?

509:デフォルトの名無しさん
06/06/10 17:47:33
>>508
>入れ子セマフォア
>多重セマファオ
おチツ毛

510:506
06/06/10 19:05:08
>>507
ご返信ありがとうございます。
trylock とは「lock が可能な状態であれば lock を実行し、そうでなければなにもしないで
終了する」処理との理解で正しいでしょうか。trylock が失敗した場合の処理を実装できれば
よいのですが、出来るだけ単純化したいと考えており、今回の件では少し辛いです。すみません。

>>508
ご返信ありがとうございます。
知識が足りず「入れ子セマフォ」「多重セマフォ」の言葉が分かりません。
検索も試したのですが... すみません。

今回はスレッドを使用していないので基本的にはプロセス単位で考えています。
目的としては同一プロセス(スレッド)による lock でデッドロックを発生させないように
する方法を探しています。ご例示頂いた異なるスレッドによるデッドロックは‥‥実際にやって
いたのですがw、プログラムを直してうまく動くようになりました。

先の投稿に記述した「やりたいこと」について考えていたのですが、以下のようにすれば
出来そうに思えてきました。
・2つめの unlock 位置の判定の件は「カウンタ」の管理で解決できそう
 (もっと良い方法があるようでしたらご教示頂けると嬉しいです)
・1つめのネスト時のデッドロック防止については、セマフォのキー値毎に最後に lock を
 掛けたプロセス(スレッド)を識別出来るようにして、それが自プロセス(スレッド)で
 ない場合だけ lock 処理を実施する

上記の「最後に lock を掛けた(sembuf.sem_op を 0 にした)プロセス(スレッド)を識別する」
方法はあるのでしょうか。お知恵を拝借できれば幸いです。

>>509
少しウケました。そのノリは高校の時以来です。w


511:デフォルトの名無しさん
06/06/10 19:54:30
>>510
URLリンク(ja.wikipedia.org)

古典的って言ったら古典的か.

512:デフォルトの名無しさん
06/06/10 19:56:50
>>510
ロックの話だけで頭がいっぱいになってるけど
そのsem1とsem2の間でどんな処理をするのか
教えてよ。

513:506
06/06/10 21:59:59
>>511
ご返信をありがとうございます。
これは「多重セマフォ」の解説(使用例の項)でしょうか?
残念ですが、今回の件は同時参照を全て止める必要があるため、初期値を大きくすることに
よって解決とすることは出来ないと思います。情報をありがとうございました。

>>512
ご返信をありがとうございます。
不要と判断していました。たとえばですが。

共有メモリにある情報をまとめたテーブルがあるとします。
関数 SetData01() はこのテーブルの特定のデータを変更します。
同様に SetData02() など複数の関数があり、それぞれ関数内部でデータを変更するための
(受取手にとってわかりやすい形から格納に適した形への変換などの)処理を実施しています。
これら関数には対応する GetData**() も存在し、変更/参照時には共に排他制御(sem2)を実施します。

更に上記個別の値をまとめて取り扱う関数として SetGroupData() なる関数があり、
先の個別にデータを変更/参照する関数を内部で使用します。
この関数でのデータの変更時には、関連する全てのデータ更新が終了するまではデータ間での
矛盾発生を防ぐために他からのデータ参照を止めたい場合があるため、この関数の実行時にも
排他(sem1)を掛けたいと考えています。

回避策として、SetGroupData() で SetData01() などを呼ばずに自前で個別データの
設定を行う方法もあるのですが、少々煩雑な処理をするところもあるため、可能であれば
SetData01() などを利用する形に出来ればと思っています。

そのままのことは書けないため、説明が足りないところもあるかと思いますがご容赦ください。


514:デフォルトの名無しさん
06/06/10 23:56:28
>>513
そのよくわからんけど、SetDataなんちゃらっていうメソッドをいくつも用意するの?
そんなことするよりもさ
SetData(class data)を用意してこいつが責任もって共有データを単独で更新すればいいんじゃないのか?
じゃあ、みんなで同時に呼べねーべバーカとか思うなら、このSetDataは要求をスタックに貯めて逐次実行する
仕組みだけを排他制御で実装すればいいよね。共有メモリに置く程度のデータならそれぐらいで間に合わないかな?

515:506
06/06/11 15:27:03
>>514
ご返信、ありがとうございます。
初めからそういう方向性を考えていれば...と後悔しているところです。(汗
次こそわ。


516:デフォルトの名無しさん
06/06/11 20:23:12
いや、変えないと今のも終わらないから。

517:デフォルトの名無しさん
06/06/12 17:52:57

質問です。
_beginThreadを使ってスレッドをつく、その中でゲームの描画をまわしているのですが

void ThreadMain(void* pParam)
{
 HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 DWORD dwLastTime = timeGetTime();
 while(!pApp->m_bStopThread)
 {
  WaitForSingleObject(hEvent, 16 - __min(16, timeGetTime() - dwLastTime));
  dwLastTime = timeGetTime();
  //実際はここで描画をするけど、今は空.
 }
CloseHandle(hEvent);
_endthread();
}

こんなことを行なうとタスクマネージャー上でCPUパワー使用率が100%近くになってしまいます。
(WaitForSingleObjectは、待機中CPUパワーを使わないとあったので期待したのですが)

Sleepあたりを入れてみたりしても、Sleep(1000);くらい大きく指定しないと使用率0%付近になりません。
スレッドを使った場合、CPU使用率は高くなってしまうものなのでしょうか?

今まではスレッドを使わず、WinMainで処理をしていたのですが、そちらでは使用率が0%に近かったです。

518:デフォルトの名無しさん
06/06/12 17:53:43

今までスレッドをやらないパターンですとこんな感じでした。
CPU使用率は常に0%付近でした。

//WinMainに
while(TRUE){
 while(0 != PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){
  if (!GetMessage(&msg, NULL, 0, 0))
   return msg.wParam;
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
 else if (16 <= timeGetTime() - dwLastTime){
  dwLastTime = timeGetTime();
  // 処理
 }
}

519:デフォルトの名無しさん
06/06/12 18:04:20
>>517
それ、WaitForSingleObject で待ってない(即リターンしてる)から。
他のスレッドが所有権を持ってないので、呼び出したスレッドが即座に所有権を得ておしまい。
2度目以降の呼び出しは、呼び出したスレッドがすでに所有権を持っているので即座に完了。

他のスレッドに所有権を持たせておくか、selectとかSleepでも使うべし。

520:519
06/06/12 19:39:57
今思いついたんだけど、とにかくタイムアウトさせたいなら
GetCurrentThread() で得たハンドルを wait してもいいのかもしれない。

521:デフォルトの名無しさん
06/06/12 19:45:59
>>519
アドバイスありがとうございます。
ただ、デバッガで追ってみましたところきちんと毎回Waitしている様子です。
Wait時間を分かりやすく5秒にしてみたところ、私の期待通りの動作をしているようです。

selectについてもこれから試してみたいと思います。

522:デフォルトの名無しさん
06/06/12 19:53:00
Sleep、WaitForSingleObject、いずれも、寝ている時間の精度自体は5msも保証できない

523:デフォルトの名無しさん
06/06/12 19:57:04
>>522
なんと、そうなのですか?
やはりFPS60なんていう精度を望む場合
Waitなんて無しでぶんまわしつづけるしかないのでしょうか?

(そもそも、Windowsで精密ゲームを作ること自体、Windowsの設計理念とは反している気がしますが)




524:519
06/06/12 20:25:43
>>521
そですか・・・ところでメインスレッド側は PeekMessage 無しに戻しましたか?
単純に >>518 から else 以降を取ってしまうと、CPU 100% のビジーループに
なるわけですが。

525:デフォルトの名無しさん
06/06/12 21:08:55
ところで、なんで、NOREMOVEでPEEKしたあと、またGetMessage呼んでるの?
単純に、直接REMOVEでPEEKして、Translate,Dispatchすればいいと思うんだけど

526:デフォルトの名無しさん
06/06/13 14:46:50
pthread_create() で作ったスレッドが終了したかどうかの確認は
どうしたらいいんでしょうか? pthread_join() してしまうとその
スレッドが終わるまで待たされてしまいますよね?

やりたいことは、複数のスレッドを作って、作った側で pthread_t
の配列にスレッド識別子を入れておき、それぞれがバラバラの
時間で終わるんですが、作った側で pthread_t の配列に入っている
値を元にそれぞれが終わったかどうかを確認して、終わっていたら
それに対して pthread_join() をやって資源開放をて、配列の側も
その部分を終了しているという値(たとえば0)にしたいんです。
(つまり UNIX で複数 fork() したあとで waitpid() の WNOHANG
みたいにして何が終わったか、あるいは何も終わっていないのかを
確認するのと同じことです)。こういうのは pthread ではどうやる
んでしょうか?


527:デフォルトの名無しさん
06/06/13 21:33:23
pthreadは詳しくないけど自分でフラグ作っても大して開発効率落ちないと思う。

528:デフォルトの名無しさん
06/06/14 00:10:40
SIG_CHLDシグナルで判断しろよ

529:デフォルトの名無しさん
06/06/14 12:15:21
>>528
pthread で作ったスレッドに対して SIGCHLD は使えないのでは?
子プロセスじゃないんだし。(Linux の実装だと使えるとか?)


530:デフォルトの名無しさん
06/06/14 13:11:53
POSIX P1003.1cにpthread_kill()ってのがあって、
signalを指定する引数に0を指定すると、
pthreadがいれば成功(シグナルは何も送られない)、
いなければESRCHのエラーになる。

processに対するkill(2)と同じ仕様。

> 自分でフラグ作っても大して開発効率落ちないと思う。

ではありますが。



531:デフォルトの名無しさん
06/06/14 13:23:26
>>530
あー! その手があったか。
くっそー。 pthread_kill() の man ページは見ていたのに気が付かなかった。

どうもありがとうございます。


532:デフォルトの名無しさん
06/06/17 17:46:23
スレッドのデバッグって何使ってますか?
Linuxだとgdbだけかな?

533:デフォルトの名無しさん
06/06/19 00:32:10
知恵と勇気

534:デフォルトの名無しさん
06/06/19 01:05:12
>>533
そんなのいらねーよ何か教えねーと食うぞ?

535:デフォルトの名無しさん
06/06/19 10:33:24
「ちびくろ! おまえを たべちゃうぞ!」と、とらは いいました。

536:デフォルトの名無しさん
06/06/19 21:49:53
>>532
かん


537:デフォルトの名無しさん
06/06/20 13:18:17
>>532
おれ、この前 gdb でやってみて大混乱。
使い方調べてから使わないといかんね。


538:デフォルトの名無しさん
06/06/24 17:19:02
無茶しやがって…

539:デフォルトの名無しさん
06/06/24 21:26:39
Windowsで、タスク内の複数スレッド間だけで通用する、高速な同期オブジェクトって無いですかね?
なんか、どれもこれも、重そうで。


540:デフォルトの名無しさん
06/06/24 23:41:41
イベント系はユーザーモードで実行される。
イベント系はプロセス間の動機にも使えるという強みがある。
クリティカルセクションのみカーネルモードで実行される。
クリティカルセクションはプロセス間の動機で使えないがイベント系に比べると
非常に高速だという強みがある

541:デフォルトの名無しさん
06/06/24 23:49:15
>>540
クリティカルセクションって何?

542:デフォルトの名無しさん
06/06/24 23:58:44
ミューテックスとほぼ同じ。
タイムアウト指定ができなかったりする。

543:デフォルトの名無しさん
06/06/25 00:07:28
カーネルモードに移行するものが高速で
ユーザーモードのまま実行できるものの方が遅いって?

544:539
06/06/25 03:10:41
クリティカルセクションだと、スレッド間での排他は楽だけど、同期には使えないよね。
イベント系はカーネルまで落ちるし、プロセス間で使えるから重いよね。

同期に使えて、カーネルまで落ちなくても良いようなヤツが欲しいンだけど、
Windowsでは用意されてない気がするんだ。
それって、正しいのかな?

545:デフォルトの名無しさん
06/06/25 03:29:24
2つのスレッドだけでいいのならクリティカルセクションでも同期は取れる。

最初にどちらかのスレッドが所有権を保持するようにする。
片方のスレッドはEnter.....()で所有権が解放されるまで待機。
所有権を持っていたスレッドが所有権を解放すれば片方のスレッドは
実行が開始されるようになる。

高速性が大事でかつ簡易な同期処理でいいならこんな方法もある。

関数自作するとか。排他制御ができれば後は自分でいろいろできる。

546:デフォルトの名無しさん
06/06/25 06:33:19
Fiberでも使ってみたら?
NT以降専用だが。

547:デフォルトの名無しさん
06/06/25 07:21:53
以前も微妙に話題になったが、MeteredSectionとか、
AdvancedWindowsのOptExとかで楽しちゃうってのもある。

MeteredSection
URLリンク(msdn.microsoft.com)

OptEx
URLリンク(www.microsoft.com)


548:539
06/06/26 17:26:10
>>545
>>546
>>547
とりあえず、情報どうも。Fiberだと排他・同期というより切替に近いので、同期にはならない気がする。

問題は、CriticalSection系は、同一スレッド上では同期しないので、>>545さんの方法、OptExはちょっと難しい感じ。
つーか、それだとどちらか片方の処理が重いときにバグになっちまう。

ということで、MeterdSectionを使うのが良いのかなぁ。でも、こいつ、CriticalSectionの拡張版みたいなもんみたいだから、
排他は出来るけど、同期は難しそう。
探したら日本語のページがあったので貼り付け。
URLリンク(www.microsoft.com)

それとも、原始的にロックファイル作るか…うーん、100近いスレッドが立ったとき考えるとやりたくないな…。
とりあえず、Mutexあたりを、最初にまとめて作成することで負担を減らすしかなさそうな感じ。
みなさん、ありがとう。
では。


549:デフォルトの名無しさん
06/06/27 21:28:46
>>548
具体的にどんな処理がしたいの?
単一プロセス内ならCriticalSection で何でも作れるよ
(だからこそOSもCriticalSectionしか提供してないわけで)。

あと「同一スレッド上では同期しないので」ってのはどういうことを
意図してるのかちょっとわからない・・・同一スレッドで非同期に
コードが実行されるのは Unix の signal のケースくらいで、
Windows のユーザモードでは起きないんじゃない?

550:デフォルトの名無しさん
06/06/27 22:11:04
>>549
ありゃ、そういう答えが返ってくると言うことは、
もしかして オレのCriticalSectionについて根本的な使い方や理解が間違ってるのかな…。

スレッドひとつしか無ければ、EnterCritical...をいくつ並べても無視されると思ってたんだけど、違うのかな…。


551:デフォルトの名無しさん
06/06/27 22:13:57
スレッドひとつならマルチスレッドじゃないからな

552:デフォルトの名無しさん
06/06/27 22:21:17
そんなにパフォーマンス気にしてるのに
何でロックファイルとかにいくんだ…


553:デフォルトの名無しさん
06/06/27 22:39:45
英語でプログラミング勉強スレ

スレリンク(english板)l50

554:539
06/06/27 22:53:13
>>551
でも、プログラムは大抵、ひとつのスレッドから開始されるんだよ。最初からふたつってわけじゃない。
まあ、だから、>>545 は使えないんだよな。


555:デフォルトの名無しさん
06/06/27 23:12:31
なにか、壮大な勘違いをしている予感

556:デフォルトの名無しさん
06/06/28 01:48:11
まず、「同期する」をどういう意味で使っているのか説明してもらってからだな

557:デフォルトの名無しさん
06/06/28 01:56:37
同期の人と一緒に仕事をする
同期するじゃね?

558:デフォルトの名無しさん
06/06/28 03:31:41
>>539
そういうのは、ふつーにeventだの何だのをでも使ってみて、重くてやってらんなくなってから考えれば良い。

559:539
06/06/28 14:26:16
>>558
なんだそりゃ。そう言う回答は勘弁して欲しいぞ。


560:デフォルトの名無しさん
06/06/28 16:09:22
なんで>>539は質問してる身分でやたらと偉そうなの?
リアルでもそういう質問の仕方しか出来ない人?


561:デフォルトの名無しさん
06/06/28 16:16:15
>>559
「回答」ではないだろう。
「重そう」と思うだけで実際にやってみることもせず
そのくせ「ロックファイル」なんて単語まで飛び出し
結局何がしたいのか、「同期」が何を指しているのかも
説明してくれない君への
アドバイスじゃまいか。

562:デフォルトの名無しさん
06/06/28 16:45:09
おまえら馬鹿なんじゃね?

563:デフォルトの名無しさん
06/06/28 16:54:40
>>560-561
ウザ

564:デフォルトの名無しさん
06/06/28 17:45:49
つーか、時々デッドロックするようなプログラムしか作ってないのかょ、おまえらは。

565:デフォルトの名無しさん
06/06/28 17:46:52
なにか、壮大な勘違いをしている予感

566:デフォルトの名無しさん
06/06/28 18:17:22
なにかが気に喰わなくて暴れ始めたお母ん

567:デフォルトの名無しさん
06/06/28 18:54:40
予感でプログラムが組めるヤツはニュータイプ。


568:デフォルトの名無しさん
06/06/28 21:21:38
まてまて。
>>539 はWindows のカーネルやAPIを設計した人たちや
普段からマルチスレッドAPなんかさんざ書いてる漏れも
見落としている、何か難しい問題に対処しようとしてるんだよ。

それはたぶんロックファイルと関係のあるなにかなんだろう。
漏れには想像もできないが、頭ごなしに否定しないでだまって
観察してあげるべきじゃないか?

569:デフォルトの名無しさん
06/06/28 22:34:06
なにか、壮大な勘違いをしている予感

570:asdlman
06/06/28 22:40:26
>>569
>>555
lead reth !!!


571:asdlman
06/06/28 22:47:52
>>569
>>555
test


572:デフォルトの名無しさん
06/06/28 23:21:13
Vistaから同期IOのAPIがキャンセル可能になるそうですね!

573:デフォルトの名無しさん
06/06/29 13:12:51
それは、非同期IOのことだろ。


574:デフォルトの名無しさん
06/06/29 15:47:52
>>573
同期IOだよ。非同期IOのキャンセルならWindows98でも出来る。

575:デフォルトの名無しさん
06/06/29 15:54:38
それを非同期というのではないのか?

576:デフォルトの名無しさん
06/06/29 16:11:59
>>575
めんどくさいなーもう。ほらよ↓
今まではCerateFile なんか非同期版がなかったからキャンセルできなかっただろ?

URLリンク(www.microsoft.com)

577:デフォルトの名無しさん
06/06/29 16:29:46
>>575
いや、絡んでるつもりは全くなかったんだ、すまん。
つまり、同期I/Oを他のスレッドで実行することによって擬似非同期I/Oの
ような使い方をしたときに、そのAPIの実行をキャンセルすることができる
ようになったということだな。
同期/非同期とはそういうことだったのか。勉強になった。

578:デフォルトの名無しさん
06/06/29 16:30:17
s/>>575/>>576/

579:デフォルトの名無しさん
06/07/01 17:16:56
Linuxのカーネル層でマルチスレッドのような
設計が必要になっているんですが、
Aという関数が終わったらBの関数で
止めていたところが動き出すような設計って
どうやったら良いもんですか?

セマフォを使った排他処理ってデータに
対する排他処理になると思うんだけど、
そういう形で発想の転換をしないと駄目なのかな?



580:デフォルトの名無しさん
06/07/01 19:10:53
待ちたいところでスピンロックでもasm WAITでもなんでもしておけばいいだろう


581:デフォルトの名無しさん
06/07/01 21:33:47
>>579
condは適当に初期化。

A() {
~;
pthread_cond_signal(&cond);
return;
}

B () {
pthread_cond_wait(&cond);
~;
return;
}



582:デフォルトの名無しさん
06/07/01 22:07:31
>>581
参考になります。

これってAのreturnの直前でBが動き出す
ということですよね?
Aが終わってからってのはやっぱり難しいのかな。

583:デフォルトの名無しさん
06/07/01 22:20:08
>>582
AA() {
A();
pthread_cond_signal(&cond);
return;
}


584:デフォルトの名無しさん
06/07/01 22:23:13
>>522
昔の奴へのレスで恐縮なんだがWindowsのSleepってそんな精度悪かったっけ?
::timeBeginPeriodとか使っても駄目?

585:デフォルトの名無しさん
06/07/01 22:49:29
他に忙しく仕事をする連中が居なければ、だいたいは大丈夫かもね。

586:デフォルトの名無しさん
06/07/01 23:26:40
>>585
なるほど
まあそれほど信用できないってことか。

587:デフォルトの名無しさん
06/07/02 00:04:19
スレッドの教科書ってどんなのあるの?
アルゴリズム系に強いやつが欲しい

588:デフォルトの名無しさん
06/07/02 00:14:48
OSによって違うな。
pthreadなら>>1->>9辺り見て。

589:デフォルトの名無しさん
06/07/02 00:18:29
Lamport's bakery algorithmとかさこんな古典的なやつから
今の新しいアルゴリズムまで載ってるのないのか.....

590:デフォルトの名無しさん
06/07/02 00:49:51
>>583
AAは別の人のソースなので手を加えられないのです。
でも参考になりますた。
ありがとうございますた。


591:デフォルトの名無しさん
06/07/03 06:53:31
windows には win32 API で色々なイベントを使えるようになってますが、
UNIXではpthreadのイベントを使う以外にないのでしょうか?

592:デフォルトの名無しさん
06/07/03 07:26:25
>>591
例えばこういう奴?
URLリンク(www.monkey.org)

どの UNIX を対象にしているかで答えも変わるけど、大抵はググれば色々出て来る。

593:デフォルトの名無しさん
06/07/05 10:16:26
Winsock、_beginthreadで起動して、
グローバル変数で終了要求するような、
簡単なスレッド書いているのですが、、、。

スレッド内でrecv()のような、
ブロックするような関数を呼びたくなりました。
これを終了するにはどうしたらよいでしょう。

594:デフォルトの名無しさん
06/07/05 10:30:57
ソケットオプションでノンブロッキングにすればいいんでない?

595:デフォルトの名無しさん
06/07/05 11:33:24
594>
ありがとう、そうします。

一般的にはどうでしょ?
ブロッキングするような関数をスレッドで呼んではいけない?



596:デフォルトの名無しさん
06/07/05 11:51:06
ブロッキングするべき状況と、そうでない状況がある。
前者ならブロックさせとけばいいし、そうでなければ非同期APIを使うか、
別個にスレッドを作ればいい。


597:デフォルトの名無しさん
06/07/05 11:59:52
>>593
recv()呼ぶ前にMSG_PEEKしておくなりしとかんとあかんよ。
#つーか、TCP受信処理を途中で終わらせると言う仕様そのものが如何なものかと。

598:デフォルトの名無しさん
06/07/05 13:48:39
>>595
一般的かどうかは知らないけど、普通はselect使うんじゃないかな。

599:593
06/07/05 13:49:40
>>596
「強制終了」以外は普通にブロックして、データが届いたときだけ
処理してくれればいいんだけど。って状況でした。
非同期っていうと、WSAEventSelect, WSAAsyncSelectで、通知を待つって
ことでよいですよね?

>>597
ちょっとわかんないのですが、
MSG_PEEKで、受信データが無いときはどうやって次の受信データを待つのが綺麗?
あと、途中で終わらないとしたら、どうやって終わるのがよいですか?


600:デフォルトの名無しさん
06/07/05 18:14:11
>>599
WSAAsyncSelect(s, hwnd, 0, 0);
shutdown(s, 1);
while (recv(s, buf, buflen, 0) != 0) {}
closesocket(s);


601:デフォルトの名無しさん
06/07/05 19:33:20
>>600
それ先方がデータ送ってくれないとCPU100%のビジーループ。
サーバアプリでは非常によろしくないコーディング。

602:デフォルトの名無しさん
06/07/05 19:50:55
recvって、ブロックするんじゃないの?

603:デフォルトの名無しさん
06/07/05 19:54:13
スマソ。ノンブロッキングのソケットと勘違いしてた。

604:デフォルトの名無しさん
06/07/05 20:35:06
WSAAsyncSelectした時点でノンブロックになる

605:593
06/07/06 17:50:25
任意のタイミングで終了させたいスレッド内では、ブロックする関数は呼ぶな。
socketはデフォルト非同期で。
で理解しました。 ありがとう。


606:デフォルトの名無しさん
06/07/06 19:44:58
>>605
そう理解したんならそれでもいいが・・・

607:デフォルトの名無しさん
06/07/06 22:55:34
ソケットを任意のタイミングで終了させると再起動したときにわややがな。

608:593
06/07/06 23:34:44
>>607
どゆこと?
例えばサーバ的なアプリで、その受信用スレッドを、サーバ的なアプリ
のユーザ都合でブチっとしたくなった場合、、、
受信処理を終了させて、クローズなり何なりをしたい。
そんな場合ですが、再起動とは、ここでサーバ的なアプリを再度起動して
受信を始めようとした場合になにかが起こるってことですか?




609:デフォルトの名無しさん
06/07/07 00:34:15
下の層が受信しているのにアプリが落ちたら、次に起動するときにbindErrorになる。

610:デフォルトの名無しさん
06/07/07 00:43:27
つかさ、断片的な情報を積み重ねて信頼性のないアプリ作るよりさ、
ばしっとWinsock Programmer's FAQとか、Winsock関連書籍を読み
とおして、きちっとしたアプリを作ろうとは思わんのかね。

611:デフォルトの名無しさん
06/07/07 01:07:01
>>609
アドバイスするなら、その前にFAQくらい読んどけよ。
知識足りなさ過ぎ。

612:593
06/07/07 10:11:03
>>610
終了するときは、shutdown(sock, 1) をスレッドの外から呼べ、
そうするとrecvが0返すので、スレッドを抜けろ。
で、理解しました。ありがとう。


613:デフォルトの名無しさん
06/07/07 11:42:52
>>609
100%賛成して同意して応援します。
他人のいう事に惑わされたりマニュアルやFAQを読んだりせず、
先方が送信を続けている間は終了できないプログラムを作り続けてください。

614:デフォルトの名無しさん
06/07/07 11:56:22
>>593
fcntl(s, F_SETFL, O_NONBLOCK); って使えない?
(Windowsだとこれはないのかな?)
>>595
select() 使う場合は他のスレッドが同じソケットから読まないように
作る必要がある。recv() ではあまりないかも知れないが、サーバ用に
bind() した一つのソケットに対して複数のスレッドから accept()
する場合にselect()使うとハマる(2つ以上のスレッドがselect()を通過
した場合に一つのスレッド以外がブロックする)。防止するには上に
書いたような fcntl() で O_NONBLOCK セットして accept() で止まら
ないようにする。
>>609
最初に setsockopt() で SO_REUSEADDR をセットしとけばいいんじゃないか?


615:デフォルトの名無しさん
06/07/08 02:08:08
volatile最強

616:デフォルトの名無しさん
06/07/08 10:36:46
メモリモデル勉強しる

617:593
06/07/09 20:09:28
最後にもひとつ。
一般的に、マルチスレッドで使われることを前提にした、受信待ちのような
ブロックする関数を提供しようとした場合は、それと一緒に受信を中断
して安全に返るための、他のスレッドから呼ばれる関数(socketの場合のshutdown)
を提供すればよい。
ですか?
他に綺麗な方法あったら教えてください。


618:デフォルトの名無しさん
06/07/09 20:26:23
一般的には、recvでブロックさせるのではなく
select系でブロックさせて
selectをブレークさせる方法を使うだろ。

つまり「外部から解除できないブロッキング関数ではブロックさせない」と。

619:デフォルトの名無しさん
06/07/09 20:28:20
selectってキャンセル可能だっけ

620:デフォルトの名無しさん
06/07/09 20:36:02
selectで同時にパイプを待ったり
WSAEventSelectで同時にEventを待ったり
というやり方のこと。

621:デフォルトの名無しさん
06/07/09 20:39:08
selectでtimeout設定すればいいと思うけど
それとももっと高度な制御がしたいの?


622:デフォルトの名無しさん
06/07/10 00:20:40
>>621
timeout 値の設定がめんどい。

仕方なく >>620 の WSAEventSelect 使ってるけど、
これはこれでめんどい。

623:デフォルトの名無しさん
06/07/10 03:56:03
pselect

624:593
06/07/10 10:22:26
>> 618
なるほど。
Linuxでは、読み込むものは全部ファイル(ファイルデスクリプタ)で、
中断など例外的な処理は全部シグナル。と思ってpselectで綺麗にい
けていたんだけれど、
Winにいったら、いろんな方法がありそうだけれど、どれもいまいちに見えて。。
WSAEventSelectは、socket以外にも汎用的に使ったりする?




625:デフォルトの名無しさん
06/07/10 11:23:05
>>617
スレッド(タスク)開始、実行状況(実行結果)の取得、完了待ち、中断のための関数を
それぞれ提供するのが一般的だと思います。
あと場合によっては先方のスレッドでコールバックされる実行状況の通知のための
コールバック関数なんかも設定できると UI 作るときには便利(プログレスバーとか)。

>>624
個人的な意見だけど、Windows では(ソケットなら WSAEventSelect等も使って)
(Msg)WaitForMultipleObjectExで待機、何かあれば処理するというのがマルチ
スレッドの場合の定石だと思います。
ソケットだけ相手にするなら単にclosesocketしてしまうというのもアリだと思うけど。

>WSAEventSelectは、socket以外にも汎用的に使ったりする?
ソケットを相手にしないのにWSA~を使う局面は無いと思う。

626:デフォルトの名無しさん
06/07/11 00:19:53
>>624

Winでも sock をファイルとして扱えるよ。

627:デフォルトの名無しさん
06/07/18 19:03:35
Linux (Kernel 2.6.17) で、pthread_create() で複数スレッドを作り、
そのスレッド全てが同一の bind(), listen() されたソケットに対して
accept() を行うプログラムを作ったのですが(O_NONBLOCKなソケット
ですが)、クライアントプログラムから複数 connect() すると、
accept() が同じ値のファイルディスクリプタを返して来ます。処理を
単純に書くとこんな感じです。

for(;;) {
 int cs = accept(...); // ここで cs が別スレッドと同じ値になる。
 if (cs == -1) {
  if (errno == EAGAIN) {
   usleep(50000);
   continue;
  } else {
   break; // error
  }
 } else {
  proc(cs); // cs を使った処理。
  close(cs);
 }
}

accept() の前後に pthread_mutex_lock(), pthread_mutex_unlock() で
ロック、アンロックをしても同じでした。

これって Linux のバグなんでしょうか?
これを回避するにはやはり accept() をするスレッドを一つにしないと
駄目ですか?


628:デフォルトの名無しさん
06/07/18 19:04:29
すいません。質問なのに age 忘れました。age ておきます。よろしくお願いします。

629:デフォルトの名無しさん
06/07/18 19:32:26
わざわざageんなよ

630:デフォルトの名無しさん
06/07/18 22:10:43
コンパイル・リンク時のコマンドライン見せろ

631:デフォルトの名無しさん
06/07/19 01:14:42
>>627
> accept() の前後に pthread_mutex_lock(), pthread_mutex_unlock() で
> ロック、アンロックをしても同じでした。

この時点でプログラミングの問題じゃないことに気付け。

632:デフォルトの名無しさん
06/07/19 01:56:34
>>627
>これって Linux のバグなんでしょうか?
つかその前に、どこで習ったんだそんな阿呆な手順。

633:デフォルトの名無しさん
06/07/19 02:07:07
acceptしてからthreadおこせ

634:デフォルトの名無しさん
06/07/19 03:17:38
>>627
よく知らんけど、下記のApache のディレクティブの存在なんかを見ると
accept は直列化 (同時に1つのプロセス・スレッドからのみ呼ぶ)するのが
普通なんじゃないかと思うが・・・

URLリンク(httpd.apache.org)

635:デフォルトの名無しさん
06/07/19 09:14:39
>>630
gcc hoge.c -lpthread

>>631
どういう意味ですか? 同時に複数のスレッドが accept() しないように
しただけですが?

>>632
これは阿呆な手段ですか? 何故? その辺詳しく教えてもらえますか?
どこで習ったかは記憶にありません。ただ昔 Java で似たようなものを
作った時はちゃんと動いたと思いました。

>>633
それはつまり accept() は親(?)スレッド一つでやるということですね。


636:デフォルトの名無しさん
06/07/19 10:02:36
accept()を排他しても、
そのプログラムがまともにうごかん事に疑問はないのか?

他の部分がおかしいだけではないのか?

637:デフォルトの名無しさん
06/07/19 11:14:26
>>636
そこが疑問ですよ。なんで既に取得してオープンされているファイル
ディスクリプタと同じ値のファイルディスクリプタが返って来るのか
という点がね。

気になるのは Linux の場合スレッドは clone() システムコールで作った
特殊な別プロセスであるということです。別プロセスだから複数スレッドで
accept() した時に同一ファイルディスクリプタが取れてしまうんじゃない
かな、とは思ったんですが、確証がなかったので質問したんです。
(Linux板の方で質問した方がよかったかな? でも他のOSではこういうのは
できないのかも少し気になる)。

で、その後、accept() を一つのスレッドでだけやって、他のスレッドは
待機させておいて、accept() 成功後にファイルディスクリプタを待機
スレッドに渡すように作り替えたらちゃんと動くプログラムは作れました。
理由はどうあれこういう風にするか、あるいは accept() 成功後にスレッド
作るように書かないと駄目なようですね。


638:デフォルトの名無しさん
06/07/19 11:25:03
>>627
> int cs = accept(...); // ここで cs が別スレッドと同じ値になる。
本当にこれと同じ書き方だったんだな?
csが大域変数だったってオチがありそうだ。

639:デフォルトの名無しさん
06/07/19 11:30:07
>>638
いいえ。大域ではありません。autoです。


640:デフォルトの名無しさん
06/07/19 12:26:13
生半可な学習しないで、ファイルディスクリプタについてちゃんと勉強したら?

641:デフォルトの名無しさん
06/07/19 13:35:02
>>637
>スレッドは clone() システムコールで作った
ちょwwwwおまwwwww帰れwwwww

642:デフォルトの名無しさん
06/07/19 13:56:58
げ、pthread_createで作ってんじゃないのか・・・!!!

643:デフォルトの名無しさん
06/07/19 14:24:08
>>640
生半可? どの辺がですか?

>>641-642
pthread_create() で作ってますよ。clone() は内部動作の話です。


644:デフォルトの名無しさん
06/07/19 14:29:47
こいつむかつく~☆

645:デフォルトの名無しさん
06/07/19 14:36:37
>>643
コンパイルオプションとかはどうだろう・・・ -pthread とか付け忘れありませんか?

646:デフォルトの名無しさん
06/07/19 14:42:25
>>645
>>635


647:デフォルトの名無しさん
06/07/19 14:48:29
>>643
続きは以下で。
ネットワークプログラミング相談室 Port17
スレリンク(tech板)

648:デフォルトの名無しさん
06/07/19 14:59:44
>>646
-lpthread だけ指定して -pthread を指定していないのではないか、といっているのだが。

649:デフォルトの名無しさん
06/07/19 15:38:16
>>648
-pthread は指定していませんでしたが、man ページや info 見ると
Linux では関係ないようですよ。

念のため指定してテストしてみましたが、同じ動作になりました。


650:デフォルトの名無しさん
06/07/19 15:45:45
いい加減、誰かファイルディスクリプタの説明してやれよw

651:デフォルトの名無しさん
06/07/19 15:47:52
>>647
そっちの方がいいですか?
スレッドとネットワークと Linux が混ざった疑問なのでどこがいいのか迷ったんですが。


652:デフォルトの名無しさん
06/07/19 16:00:17
>>640>>650
pthread_createで作ったスレッド間では、ファイルディスクプリタは共有されます。
すなわち、同じ数値=同じソケット端点。
何がいいたのか知らんがこれでいいか?

653:デフォルトの名無しさん
06/07/19 16:06:07
>>651
どっちがいいのかはわからんけど、このスレじゃ解決できなさそうじゃん。

654:デフォルトの名無しさん
06/07/19 16:20:45
Linuxのスレッドが特別なプロセスだったのは、2.4より前の話だよ。
# 例えばpidやsignalの扱いなど。
>>627は、2.6.17だから関係ない。

655:デフォルトの名無しさん
06/07/19 16:21:59
>>637
> accept() 成功後にスレッド作るように書かないと駄目なようですね。

そんなことはない。

656:デフォルトの名無しさん
06/07/19 16:22:13
>>652
それは知ってますよ。だからこそOSがおかしいんじゃないかと思ったんですから。

元々の質問を要約すると、まだ close() されていないファイル
ディスクリプタの値を accept() が返して来るのは何故かです。
一つのスレッドが accept() で 5 を受け取ったとして、それが
close() される前にもう一つのスレッドが行った accept() が
受け取ったファイルディスクリプタの値も 5 だったということです。
これ、accept() を一つのスレッドでしかやらなければ当然 6 などの
違う値が返って来ます。

>>653
今のところそんな感じしますね。


657:デフォルトの名無しさん
06/07/19 16:24:17
>>654-655
そうですか…。じゃあ何でだろう?


658:デフォルトの名無しさん
06/07/19 16:26:01
こっちの方がいいかも。
UNIX板 pthread地獄
スレリンク(unix板)
読んでる人はこの板と重複がかなりあるかもだけど。

659:デフォルトの名無しさん
06/07/19 16:34:42
>>658
そこはたしかに近いこと話し合われてたスレですね。
じゃあそこに移転します。

こちらのスレのみなさまありがとうございました。


660:636
06/07/19 23:13:46
な?


661:デフォルトの名無しさん
06/07/20 01:05:07
うはwww
ボッコボコwww
しかも自分のミスwww

662:デフォルトの名無しさん
06/07/20 12:50:33
>>640>>650
お前等も黙ってないで「ファイルディスクリプタの説明」してくれよw

663:デフォルトの名無しさん
06/07/20 13:12:28
File Disk Riptor 略して FDR である

664:デフォルトの名無しさん
06/07/20 14:35:46
なんか車の駆動方式っぽい略称だな。

665:627
06/07/20 16:04:12
申し訳ありません。私がバグっておりました。

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

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

ということでお騒がせしました。
Linux でも複数スレッドからの accept() は問題無くできます。

666:デフォルトの名無しさん
06/07/20 16:25:36
まあせいぜい地雷原を走り抜けてくれ

667:デフォルトの名無しさん
06/07/21 20:41:07
Javaだと複数のスレッドがacceptでブロックしてても動いたと思う。
URLリンク(www.amazon.co.jp) の例の1つにあったと思う。

個人的にはとても気持ち悪いし、他の人にコードを見せると頭を抱えるし、
特にメリットも思いつかないので、
自分はJavaでもacceptは1つのスレッドで実行してる。

668:デフォルトの名無しさん
06/07/21 20:54:45
この人の場合、さらに non-blocking にしてあって、ブロックしないでポーリングしてるらしいよw

669:デフォルトの名無しさん
06/07/21 21:16:04
>>667
> 特にメリットも思いつかないので、

はあ


670:デフォルトの名無しさん
06/07/22 00:47:01
試したことはないが、
複数のThreadがServerSocket#accept()でブロックされてるとき、
ブロック解除で起こされるThreadはたぶん唯1つなのがメリットじゃないかな。
単一のThreadがaccept()待ち→ブロック解除→Queueに放り込んでWorker Threadを
たたき起こすパターンだと、Queueを監視する複数のWorker Threadがいったん
たたき起こされるから。


671:デフォルトの名無しさん
06/07/23 09:39:44
pThreadsについての書籍を探してるのですが、以下のもの読まれてる方
感想はどうですか?良書ですかね?

URLリンク(www.amazon.com)

URLリンク(www.amazon.com)

672:デフォルトの名無しさん
06/07/26 17:24:59
お世話になります。
識者のご意見ください。

以下のような状況です。(環境はVC6のWin32API)

メインスレッドAと、待機スレッドBがあります。
BはSuspend状態です。

あるタイミングでAがBに仕事を投げてResumeしました。
Bは仕事が終わったら自分でSuspend状態になりたいのです。

Bは自分のHANDLEをSuspendThreadしちゃってもいいものでしょうか?
AがBのフラグを見てSuspendしてやるというのはちょっと効率が
悪い気がします。

以前はBを待機スレッドではなく、その都度生成して自殺させていました。
が、この方法だとデバッグウインドウに生成と消滅のメッセージが
出まくるのと、やはりCreateThreadの負荷が気になります。

こういう場合の常套手段など、ご教示ください。
待機スレッドがCPUを食わないようにするために、Suspend状態に
しておく、という風に考えるのは変でしょうか?

よろしくお願い致します。

673:デフォルトの名無しさん
06/07/26 17:36:12
>>672
ただのワーカースレッドでええんちゃうかと
マイクロスレッドのようなものを考えてるなら、ファイバでも使えばいい


674:デフォルトの名無しさん
06/07/26 17:36:23
>>672
自分をSuspendするのは悪くない。というか、それが唯一のSuspendThreadの正しい使い方。
基本的には自スレッド以外をSuspendThreadしてはいけない。

ただし、普通はautoresetのイベントハンドルを用意して WaitForSingleObject で待たせておき、
SetEventで起こす。これはAがBをResumeThreadで起こすのが難しいから。

具体的には、SuspendThread/ResumeThreadで待機を実現しようとすると、
ResumeThreadするときに、ちょうどBが何かの仕事を終えてSuspendThreadする
直前だったりするとResumeしても即Suspendしてしまうので、これを避けるために
クリティカルセクションとフラグが1つ余分に必要になってしまって効率も悪いし
コードもムダに複雑になる。


675:デフォルトの名無しさん
06/07/26 18:07:51
みなさん、レス有難うございます。

>>674
>autoresetのイベントハンドルを用意して WaitForSingleObject で待たせておき

こんな感じでしょうか?

スレッドB{
while(1){
WaitForSingleObject(XXX);
何か仕事(B*)
}
}

スレッドA{
while(1){
何か仕事の準備(実行中のB*の部分を触らない配慮はしている)
SetEvent(XXX);
}
}

>直前だったりするとResumeしても即Suspendしてしまうので
なんとなく現象の心当たりがあります。



676:デフォルトの名無しさん
06/07/26 18:21:59
>>675
Bが待機するところはそんな感じです。

あとまぁよく使うパターンとしては
(1) AがBの仕事の完了を待たずににいくつもの仕事を投げておけるようにQueueに仕事を登録して SetEvent する。Bは起こされたら、Queueにある仕事を全て実行してからWaitする。
(2a) 「仕事終わったよイベント(初期値はON)」ってのも用意して、Bが仕事を終えたらSetEventする。Aは仕事終わったよイベントを待ってからBを起こす
(2b) CreateSemaphoreでMaxCount 1 のセマフォを作って、AはWait,→仕事の準備→ReleaseSemaphore、
  BはWait→仕事を取り出して実行→ReleaseSemaphore とする。

仕事が終わったかどうか知りたくなることも多いので、漏れは2aのパターンを多用します。
殆ど等価な 2b でもいいのかも知れない。

677:デフォルトの名無しさん
06/07/26 19:36:15
>>676
Suspend,Resumeでやってたところを待機オブジェクトにしました。
すっきりした感じがします。
>(2a)
なんとなくこれっぽいことはやっていました。
どうもありがとうございました。

678:デフォルトの名無しさん
06/07/26 21:47:50
lock-freeについて調べている内に
CAS(CompareAndSwap)という概念にたどりついたのですが
ちょっと教えてください。
/* 関数内の処理はatomicに処理されると仮定*/
bool CAS(void*addr,int expval,int newval){
if(*addr == expval){
*addr = newval;return true;
}
return false;
}
*addr=0;
while(!CAS(addr,0,*addr + 1)){
//※ここでコンテキストスイッチ
}
//アトミックにインクリメント成功?
例えば※の部分で別スレッドがaddrの値を5に変更→0に変更
という動きをした場合、*addr == expvalが成り立ってしまい、
インクリメント成功とみなされてしまう気がするのですが・・・
何か回避策等あるんでしょうか。それとも俺の理解不足なんでしょうか

679:デフォルトの名無しさん
06/07/26 23:07:03
>>678
「アトミックなインクリメント」というものを理解していないような気がする。
過去に5だったかどうかはさておき、他のスレッドで0にされたものが1に
なるのだから成功している。
というか5で放置されてて6になってもやはり成功。

*addr=0;
IntgerlockedIncrement(&addr); ←APIによるアトミックなインクリメント
などとしたところで、この2行の間に*addrが5になって0になることもある。

「アトミックなインクリメントに失敗」というのは、2つのスレッドで1度ずつ
アトミックなインクリメント操作が行われたにも関わらず2増えないことを言う。
これは正しい実装では決して起きない。

680:デフォルトの名無しさん
06/07/26 23:07:59
追記:
CASによるアトミックなインクリメントの実装は、正しくは↓

while (!CAS(addr, *addr, *addr+1) {}


681:678
06/07/27 21:49:17
>>679
>>680
ありがとうございます。

addr=&val;
while(!CAS(addr,*addr,*addr + 1)){
//※ここでコンテキストスイッチ
}
でも問題が起きそうな気がするんですが・・

とここまで書いて
URLリンク(www-06.ibm.com)
に似たような事が書いてありました
ABA問題というらしいですが

もうちょっと勉強してでなおしてきます・・

682:デフォルトの名無しさん
06/07/27 23:41:31
とりあえず、CAS(xxx, *addr, *addr+1)
なんて書いている奴は氏んでいいよ。

atomic_inc(int *addr)は
do {
 int var = *addr;
} while (!CAS(addr, var, var+1));
にしないと。

まあ、複数のスレッドで勝手に値をセットするような変数を
特定の個所だけatomic_incを使っても意味は無いがね。

683:デフォルトの名無しさん
06/07/28 00:03:12
終わった話題についてなにを得意げに語ってるんだろう…。

684:デフォルトの名無しさん
06/07/28 00:20:12
>>682
それC言語的にやばいやん。

685:デフォルトの名無しさん
06/07/28 00:31:47
つまり、「ほんと、バカしかいないんだね」ってことか。

686:デフォルトの名無しさん
06/07/28 00:43:19
やーい
ばかー

687:デフォルトの名無しさん
06/07/28 07:26:02
volatileですべて解決!

688:デフォルトの名無しさん
06/07/28 12:24:47
>>682
バカは喪前のほうだと思うが・・・
なぜ自分がバカなのかが知りたかったら、
元のコードの問題点を書いてご覧よ。
書いてるうちにわかるだろ。

689:デフォルトの名無しさん
06/07/28 17:51:17
元のコードの問題点は関係なくて
*addrを2度読み出して同じ値が取れると思っているのがバカだって事だろ。

690:デフォルトの名無しさん
06/07/28 17:53:25
しかも、この手のバグは非常に表面化しにくく
再現性が低い(デバッグが難しい)。

691:デフォルトの名無しさん
06/07/29 15:08:13
volatileですべて解決するという忠告がみえないのか?

692:デフォルトの名無しさん
06/07/29 16:14:19
別CPUから発言が見えるようになるまでには時間がかかります

693:デフォルトの名無しさん
06/07/29 18:15:53
VC++とMFCでマルチスレッドなサーバープログラムを書いています。
サーバープログラムを終了する時、ソケットが走ってるスレッドを終了させないといけませんが、
スレッドに終了を通知する手段が分かりません。
どのように終了を通知するのか教えていただけないでしょうか。

よろしくお願いします。

694:デフォルトの名無しさん
06/07/29 19:01:50
ソケットをどういう風に使ってるかによると思うけど、イベントとか単なるフラグとか。

695:デフォルトの名無しさん
06/07/29 19:36:20
>>693
ExitProcessで自殺すればおk

696:693
06/07/29 19:49:37
CAsyncSocketを継承して作ったUDPのソケットです。
クライアントからやってくるパケットをRecvFromで受けて、データに応じてSendToしているだけです。

現在、スレッドを閉じるのにdeleteでデストラクタを呼び、強制的に終了させているのですが
デバッガで追っかけていくとCAsyncSocketの中でエラーが発生します。
詳細は不明ですがおそらくソケットを閉じずに終了したためではないかと思います。

Win32APIでマルチスレッドなプログラムを組んだときはPostThreadMessageで終了メッセージを
送って、WaitForSingleObjectでスレッドが落ちるのを待っていたのですが、MFCで
そのような手順を踏んだ終了の仕方は(強制終了じゃないやり方)ないのでしょうか?

697:デフォルトの名無しさん
06/07/29 20:28:56
CAsyncSocketて使ったことないから知らないけど、
非同期に通信してるなら終わりにするかどうか判断する機会はあるんじゃないの?

698:デフォルトの名無しさん
06/07/29 20:48:34
CAsyncSocketのデストラクタが動けば万事OKみたいなことMSDNには書いてあるけど。
スレッドを強制終了するから、そのスタックにあるCAsyncSocketがリークしてるとか、
そういうこと?

699:693
06/07/29 21:12:35
>>697
複数台の設備との通信をするサーバープログラムなのですが、設備のON/OFFとサーバーのON/OFFは
必ずしもリンクしていません。一応作業標準として順序だてることは可能ですが、予想外のトラブル(瞬停など)を
考えると何かのパケットが来たらソケットを閉じてもいいとはできません。
サーバープログラムを閉じる作業中にソケットが走っているスレッドに終了を通知できればいいのですが
その方法がわからないのです。

>>698
>そのスタックにあるCAsyncSocketがリークしてるとか
そのとおりです。

700:デフォルトの名無しさん
06/07/29 21:18:08
スレッドが終了する時のイベントハンドラで
CAsyncSocketをdeleteじゃダメって事?

701:デフォルトの名無しさん
06/07/29 21:24:23
>>700
今はスレッドのデストラクタでCAsyncSocketをdeleteしていますが、その中でエラーになります。

702:デフォルトの名無しさん
06/07/29 21:38:00
ねぇ。マルチスレッドって何?

703:デフォルトの名無しさん
06/07/29 21:40:39
multi 【名-1】 (複数{ふくすう}の色調{しきちょう}からなる)縞模様{しま もよう} 【名-2】 マルチビタミン(錠剤{じょうざい})
thread 【名-1】 (繊維を束ねた)糸、より糸 【名-2】 糸[繊維]状のもの、細い筋状のもの 【名-3】 (全体をつなぎ止める)筋、(話などの)脈絡{みゃくらく}


704:デフォルトの名無しさん
06/07/29 21:53:15
縞模様の筋ですか?

705:デフォルトの名無しさん
06/07/29 21:55:30
筋肉のことですか?

706:デフォルトの名無しさん
06/07/29 22:29:03
>>691
まさかとは思うけど、本気で言ってるわけじゃないよね?

707:デフォルトの名無しさん
06/07/30 00:24:25
>>689
だって別に同じ値じゃなくても問題ないんだよ。
単にその1度のCAS呼び出しがfalseになるだけ。


708:デフォルトの名無しさん
06/07/30 00:32:23
>>707
第3引数の *addr + 1 を評価した後に別スレッドによって *addr の値が変更され、
その後に第2引数の *addr が評価されるとアウト。

709:デフォルトの名無しさん
06/07/30 09:43:28
>>701
スレッドを強制終了させないで、外部から何かきっかけを与えて自分で終わるようにすればいいだけじゃん。

710:デフォルトの名無しさん
06/07/30 15:36:23
>>691>>707
>>708の言うように、
「CASの第2引数の値」と「CAS呼び出し時に*addrに入っている値」
これが違うのは問題ないが
「CASの第2引数と第3引数の値の差」が1でない場合に誤動作する。

コンパイラの最適化で読み出しが1回になるケースもあるだろうが
最適化オプションで動作が異なるのはデバッグを難しくするだけ。

volatileを使えば、読み出しが2回になることが保証されるだけ。

711:デフォルトの名無しさん
06/07/31 13:37:43
一般的な双方向リストをマルチスレッドで使うとまずいですか?

new -> next = next;
/* ここでスレッドが切り替わるとか? */
new -> prev = next -> prev;

みたいな事が起きるとうまく繋げないような気がします。
WinAPI を使ってオブジェクトかなにか?を作って排他制御する
必要があるのでしょうか?

712:デフォルトの名無しさん
06/07/31 13:41:09
問題ないw


713:デフォルトの名無しさん
06/07/31 15:11:21
>>711
まずい。複数スレッドからappendすると、ノードが行方不明になったりする。
ただ、スレッドセーフな双方向リストにするより、
外部の同期オブジェクトを使ってそのリストへのアクセスを同期化する方が
柔軟。

714:デフォルトの名無しさん
06/08/01 06:53:40
volatileですべて解決!!!

715:デフォルトの名無しさん
06/08/01 10:44:44
この話では無理w

716:デフォルトの名無しさん
06/08/01 11:20:51
>>711
問題ない
関数内ではスレッドの切り替えは起こらない

717:デフォルトの名無しさん
06/08/01 11:51:13
preemption はいつでも起こりうるでしょ

718:716
06/08/01 12:39:23
起こらないでしょ


719:デフォルトの名無しさん
06/08/01 12:43:33
>>716
何を根拠に言ってんの?

720:デフォルトの名無しさん
06/08/01 12:51:51
ようやくWindowsのメッセージディスパッチのことを理解したばかりのヒトが
それをマルチスレッドだと思い込んでるんでしょう。

721:デフォルトの名無しさん
06/08/01 13:19:11
>>716 は、ユーザレベルスレッドしか使った事無い人なんでしょうかね。

722:デフォルトの名無しさん
06/08/01 13:23:44
>>716はWin3.1ユーザー

723:デフォルトの名無しさん
06/08/01 13:24:48
実装がユーザレベルかカーネルレベルかと、プリエンプティブかコ・オペレーティブかは関係ないだろ。

724:デフォルトの名無しさん
06/08/01 13:33:14
関数内では起こらないってのもすごいよな。
普通は全てmainの関数内なんだが。
まあWndProcはまた別だが、それもWinMain内ででGetMessageしてるわけだし。

725:716
06/08/01 14:35:50
反省^^


726:デフォルトの名無しさん
06/08/01 22:51:18
>>723
そこに異論は無いけど、言いたい事は分かるでしょ。

727:デフォルトの名無しさん
06/08/02 08:14:08
まあ、あれだ。がんがりたまえ(笑)

728:デフォルトの名無しさん
06/08/02 12:46:56
一般的なのはミューティックスを作る方法なの?



729:デフォルトの名無しさん
06/08/02 13:49:28
ディスクトップでディスクリプタをミューティックスで保護することを考察

730:デフォルトの名無しさん
06/08/02 14:34:13
むてふ

731:デフォルトの名無しさん
06/08/02 14:47:18
ティキストエデタ

732:デフォルトの名無しさん
06/08/02 15:05:17
www

733:デフォルトの名無しさん
06/08/02 23:11:34
ヴォラタィル

734:デフォルトの名無しさん
06/08/03 08:56:51
コンピゥタァ


735:デフォルトの名無しさん
06/08/03 12:30:55
モシ NO=735 ナラバ トベ >>1000

736:デフォルトの名無しさん
06/08/03 14:38:59
static bool g;

if (!g && g = true) {}

この if ()の中でスレッド切り替えって起こります?
排他処理になりませんか?



737:デフォルトの名無しさん
06/08/03 14:54:43
>>736
その g = true というのは本当に g = grue なのか?
それとも g == true の書き間違い?


738:デフォルトの名無しさん
06/08/03 14:56:56
あ、俺も書き間違えた。すま。

739:デフォルトの名無しさん
06/08/03 15:47:48
>>736
> この if ()の中でスレッド切り替えって起こります?
起こる

> 排他処理になりませんか?
ならん

740:デフォルトの名無しさん
06/08/03 18:52:39
w

741:デフォルトの名無しさん
06/08/03 21:56:53
ちょっと待てよ。C言語だとするとショートサーキットだよな?
!g の結果が false なら g = true は実行されないよな。
true なら実行される。

排他になるんじゃないか?


742:デフォルトの名無しさん
06/08/03 22:01:59
ひょっとしたら
!g
がアトミックじゃない処理系もあるかも

743:デフォルトの名無しさん
06/08/03 22:02:10
ショートサーキットは関係ない。
!gの評価と、g=trueの間にスレッドが切り替わる可能性があれば、排他として役に立たない。

744:デフォルトの名無しさん
06/08/03 22:31:23
アセンブラレベルで考えるんだ

745:デフォルトの名無しさん
06/08/03 22:49:20
なんだろ? 書き込み見てると、CPU命令レベルでの挙動に思い至らないのが居るな。
ソースレベルの字面で捉えてコンパイルというのが何なのかまったく知らないよう
に思える。

こんなんで日本のプログラマーのレベルは大丈夫なのか? 小中学生だったら
知らなくても無理は無いのか。

746:デフォルトの名無しさん
06/08/03 23:05:44
アセンブラまで降りる必要は必ずしも無いとは思うが
メモリの読み込みと書き出しを同時(atomic)に行うことは
(普通は)出来ないということくらいは知っておく必要がある。

もちろん、プロセッサはそのための命令を(普通は)用意しているが
コストがかかるため、普通にソースを書いた場合
コンパイラはその命令を使ったコードは出力しない。

747:デフォルトの名無しさん
06/08/03 23:16:40
えらそうに講釈たれてても

> 同時(atomit)

この一言で台無しだな。

748:デフォルトの名無しさん
06/08/03 23:25:35
>>747
お前いらないから

749:デフォルトの名無しさん
06/08/03 23:36:58
必死な子がいるなぁ。

750:デフォルトの名無しさん
06/08/03 23:39:29
>>747
別のプロセッサに割り込まれないように
lock等で保護してからxchgしたりincしたりnegしたりするけど
それをatomicと言わないとでも?

例えばあるメモリの内容を+1する場合、
「+1する命令をメモリに対して発行する」ではなくて
「プロセッサがメモリを読んで、+1した値をメモリに書き込む」だし。

751:デフォルトの名無しさん
06/08/03 23:58:41
なに一生懸命説明してるの?

これスレでそんなこと知らない奴なんてあまりいないよ。

俺はただ「atomic」と「同時」って全然違うって言いたいだけなんだが。

まあ俺も atomit とか書いてるようじゃ人のことは言えないわな。(w

752:デフォルトの名無しさん
06/08/04 00:03:37
>>751
もう消えてね(^^)

753:デフォルトの名無しさん
06/08/04 00:18:24
>>751
ずいぶん必死ですね。

754:デフォルトの名無しさん
06/08/04 00:20:13
最近なりを潜めてる、某キティと文体が似てる・・・

755:デフォルトの名無しさん
06/08/04 01:02:29
読むのと同時に書かないと壊れるメモリもあるだぜ?

756:デフォルトの名無しさん
06/08/04 01:19:47
「atomic」は日本語で言ったら「不可分」ちうことですわ。

757:デフォルトの名無しさん
06/08/04 01:23:06
原子力って感じかと思ってた

758:デフォルトの名無しさん
06/08/04 03:38:13
分割不可能な最小単位つうことですょ

759:デフォルトの名無しさん
06/08/04 03:51:04
つまり、鉄腕アトムは分割不可能と言うことで宜しいか。

760:デフォルトの名無しさん
06/08/04 04:08:01
「atomic」には他に「原子の」みたいな意味もあるんですわ。
昔は原子(atom)は物質の不可分な最小単位と考えられていたので。
どっちの意味が先か知らんけどね。

761:デフォルトの名無しさん
06/08/04 07:05:02
で、何が言いたいんだ?

762:デフォルトの名無しさん
06/08/04 07:11:33
atomic bomb 分割不可能な爆弾

763:デフォルトの名無しさん
06/08/04 07:12:41
割ったら被爆しちゃうからね

764:デフォルトの名無しさん
06/08/04 07:17:17
>>761
誰でも知ってるような事をちょっと偉そうにしゃべくってみたかっただけですわ。

765:デフォルトの名無しさん
06/08/04 07:18:59
被爆と被曝

766:デフォルトの名無しさん
06/08/04 07:55:02
>>764
何のために?

767:デフォルトの名無しさん
06/08/04 07:57:34
>>760
なに一生懸命説明してるの?

これスレでそんなこと知らない奴なんてあまりいないよ。

768:デフォルトの名無しさん
06/08/04 08:37:02
「同時」って書いちゃうヤツ以外はね。

769:デフォルトの名無しさん
06/08/04 08:45:15
VRAM(昔のやつ)やWRAM(初代Milleniumが採用した奴)を思い出した。

770:デフォルトの名無しさん
06/08/04 09:45:01
>>768
どこが変なのか未だにわからんのだが?

「読み込みと書き込みが同時に出来ない」
だから
「読み込みと書き込みをatomicに出来ない」(バスロックしなければ)
という意味なんだけど?

771:デフォルトの名無しさん
06/08/04 09:48:31
>>764
俺は知らなかったからタメになりましたよ
一応ありがとう

772:デフォルトの名無しさん
06/08/04 09:53:42
この流れ見て、コンカレントとパラレルの違いが理解出来なかった当時を思い出した

773:デフォルトの名無しさん
06/08/04 10:49:55
既に「atom」という言葉があるからこそ、物質の探求の過程で原子にその言葉を当て嵌めたってことくらい
>758を理解していたら考えるまでもないだろ。

774:デフォルトの名無しさん
06/08/04 11:02:32
>>770
同時(simultaneous)と、不可分(atomic)の違い。


775:デフォルトの名無しさん
06/08/04 11:03:28
意味が分からねえ・・・

776:デフォルトの名無しさん
06/08/04 11:10:09
>>770
恥の上塗り


777:デフォルトの名無しさん
06/08/04 12:38:57
ガキ共の言葉遊びここまで

778:デフォルトの名無しさん
06/08/04 12:49:23
じゃあ今から大人の言葉遊びか・・・エロス

779:736
06/08/04 13:14:37
if (g = g ? false : true)

この場合でも排他にならない??
アホですまん

780:デフォルトの名無しさん
06/08/04 13:19:58
C言語のレベルでどの式がアトミックになるかという事に依存するのが間違いだと思う。
現存する全ての環境でアトミックに実行されるような式でも、それは処理系依存。

781:デフォルトの名無しさん
06/08/04 13:21:37
その後、原子は分割可能であることが判明してしまいました。

782:デフォルトの名無しさん
06/08/04 13:25:55
陽子と電子に分割できるんだっけ?

783:デフォルトの名無しさん
06/08/04 13:27:46
あと中間子

784:デフォルトの名無しさん
06/08/04 13:40:08
それらの素粒子も実は更に……
つーのはやめておこうか。

785:デフォルトの名無しさん
06/08/04 14:05:25
>>779
そもそもどう排他したいの?

786:デフォルトの名無しさん
06/08/04 14:21:49
mkdir() は atomic らしい

787:779
06/08/04 14:38:19
リスト処理でつなげるときに排他したいけど
WinAPI使うしかないみたいですね


788:デフォルトの名無しさん
06/08/04 14:39:02
デッドロックになってしまった場合に
一定時間後に解除するような作りにしたいとき

mkdir() だと unlink() すると atomic では
なくなってしまう危険があるので

rename() の方が良いそうです

URLリンク(www.din.or.jp)



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