6 :
デフォルトの名無しさん:04/10/21 13:16:00
ほすしてみよう
ネタ щ(゚▽゚щ) カモーン
FairThread最強伝説
9 :
デフォルトの名無しさん:04/10/25 18:51:19
Win32のスレッドでGDIオブジェクトをスレッド間で共有して
ロックせずに交互に描画なんかしたりしたらまずいよね?
なんかWeb上にそういうサンプル使って説明してる馬鹿がいたからびっくりした
はっ、漏れのHPだw
デッドロック以外にスローダウンというのがあって、こいつを回避するのは
なかなか難しいね。頭痛いわ。
確かに微妙な表現だよねw
そのサイトは初心者スレで馬鹿にされたサイトだな
要するにスレッドの実行より切り替えに時間がかかって本末転倒状態になってるのがスローダウン?
>>20 全然違う。内部でミニデッドロックが多発して、本来走っているべき
スレッドの数が大幅に少なくなっているのがスローダウン。止まらず
に動いているので一見正常に見えるが、処理速度が遅くなるので、
あちこちに不都合が出る。最終的に完全なデッドロックに移行してしまう
事もある。
設計ミスが原因。
ミニデッドロックって何だよ(w
ジャインアントロックすると簡単に起きるよね。
スーパーデッドロックとかウルトラデッドロックはもっとデッドロックだぞ。
デッドロックにミニもビッグもないだろ。バカ?
27 :
デフォルトの名無しさん:04/10/31 16:01:46
マルチスレッドとか言っても
管理に手間かかってメモリ余計に食うだけだろ
普通に処理したほうが百倍早い
>>27 たいていそうだよね (百倍速いってことはないけど)。
できるだけ避けるほうがいいと思うよ、マルチスレッド。
32 :
名無しさん@お腹いっぱい。:04/10/31 16:49:20
スーパーとかウルトラとか百倍とか、漫画みたいだな。
>>33 >>19のリンク先の説明は舌足らず。ちゃんとした本を買って勉強した方がいい。
>>22 >内部でミニデッドロックが多発して
それは普通にデッドロックって言わない?
FTPのパスワード忘れたので、無理です。
ネタですか?
ネタです。
もう寝たです。
すたべは、機会は与えられているのに、
リソースを割り当てられないエンエィティがあること。
レース状態というのは、
単にリソースを奪い合う関係にある状態のこと。
スローダウンの他にマスタベーションってのがあるから、
>>44 誰かが言うと思ってた。本当にバカなんだから。
遅漏ダウンの他に
47 :
デフォルトの名無しさん:04/11/03 16:56:43
pthreadで、スレッドが現在動いているかどうか調べるにはどうすればいいんですか?
48 :
デフォルトの名無しさん:04/11/03 17:11:41
Cで書いてるのだが、なかなかうまくいかない。
以下のようなプログラムを作ってる。
懸賞サイトをよく利用するので住所などの入力を自動にするプログラム。
配布されてるのはあるが、なんか使いにくく機能がいまいち。
サイトごとに指定できないので、入力がおかしくなる懸賞サイトがある。
51 :
デフォルトの名無しさん:04/11/04 06:15:00
gccでMPIを使えるようにするにはどのようにしたらよいのでしょうか?
MPIはスレ違い。
使えるようにするだけなら、MPIの実装をinstallしろ。それだけだ。
53 :
デフォルトの名無しさん:04/11/04 22:26:16
rand()がスレッドセーフではないのは何故ですか?
めんどいから
boost::randomはスレッドセーフじゃなかったっけ?
56 :
デフォルトの名無しさん:04/11/10 20:37:20
Win2003 Server以上でMemoryBarrierというキャッシュのフラッシュのマクロがあるのだが、
それ未満のOS(マルチCPUやHyperThreadingなども含めて)ではスレッドの切り替え時には、
同期制御をして書き換えた部分も切り替え後に値が途中までしか変わっていない
ということが有り得るのでしょうか?
通常、小さい変数などはvolatileをつけるべきだってのは知っているのですが、
const_castでvolatileを変える仕様はMS VC7.1には入っていないし、
同期をかけるクラスはすべてvolatile版も作れということですかねぇ。
DAT落ちなんですが。
その1にもありますかね?その1読み中。
にくちゃんねるで拾えば読めるよ
にくちゃんねるでその2だけひっかからず。mimizなんたらも見えず。
その1をよんだところ、マルチスレッドな環境で同期処理用の関数で
制御を行うときにはキャッシュはクリアしていなければ、まともに動作しねぇ。
マルチプロセスじゃ弱いメモリモデルというのになってるらしい。
本でもあさってみますわ
> MemoryBarrierというキャッシュのフラッシュ
微妙に誤認がある。やはりその2嫁
>>58 googleのキャッシュとか、archive.orgとか。
google cacheでその2(900ちょい前迄)よんだが、流れがつかみにくい・・・
VC++な俺は_ReadWriteBarrierでreorderされないようにバリアしろ。
Intrinsicな_Interlocked*をつかって、reorderも抑制しろ。
ソース書き直す前に、手持ちの本も読んでみます。
上手いスレッドレイプのやり方教えてくらさい。
>>64-65 ここでスレイプの練習するの止めてくれる?
自作自演で煽り煽られの状態に持ち込むのがテクニックの一つだよね?
67 :
デフォルトの名無しさん:04/11/17 14:43:47
Solarisのマルチスレッドプログラムをlinuxに移植しることになったんだけど、
なんか参考になるサイト教えてくださいおながいします。
linuxのThreadライブラリには何種類かあると思うのですがpthreadが無難なんでしょうか?
なんでオライリーのpthread本はイモムシの表紙なんですか?
気持ち悪いです。
重複スレ立てて並列実行しなくていいの?
スレの立て方の覚えたての時期は
得意げになってクソスレ立てまくるんだよな
これ、マジでシャレにならんよ
>>67 kernelのversionは新しくしてね。
古いlinuxthreadは糞だから。pthread互換じゃないから。
74 :
デフォルトの名無しさん:04/11/22 15:04:29
75 :
デフォルトの名無しさん:04/11/23 20:50:21
マルチスレッド プログラムの動作をうまく視覚化するような図法ってあるのでしょうか?
何かありましたらお教えください。お願い致します。
そういうデバッガはある。
Java言語で学ぶデザインパターン入門 マルチスレッド編にちょっと図があるけど、
Javaの範囲(モニタ)に特化してるかも。とするとpthreadだと使いにくそうな気がする。
組み込み系の本に載ってるかも…でもスレッドじゃなくて全体が並列に動くからなあ。
現在複数スレッドから共有するメモリにアクセスしたいのですが
メモリにアクセスする時にクリティカルセクションで同期をとっています。
クリティカルセクションEnter状態の時に、子関数を呼んだ場合
子関数が動作中も安全なのでしょうか。
Thread()
{
EnterCriticalSection();
Func();
LeaveCriticalSection();
}
Func()
{
共有するメモリの編集処理
}
82 :
デフォルトの名無しさん:04/11/25 18:57:55
マルチスレッドってそもそもまに?
一つの掲示板にスレッドがいくつも立てられること
>>79 他スレッドはEnterCriticalSection()から返ってこない。
動作を見れば簡単にわかるだろうに・・・。
85 :
デフォルトの名無しさん:04/11/29 05:20:34
pthreadで優先度を変えてスレッドを実行するにはどうしたらよいのでしょうか?
>>85 pthread_setschedparam()
ネーミングセンスを疑う>pthread_〜
Linuxで、pthreadを用いたマルチスレッドプログラムを作っています。
pthread_cond_wait関数を用いて待機させ、
pthread_cond_signalやpthread_cond_broadcast関数を用いて
待機スレッドを起こしています。
ここで質問ですが、
ある時点において、待機中のスレッドがあるかどうか、
できればいくつあるのか、を拾う術はあるのでしょうか。
ある待機中のスレッドをpthread_cond_signal関数で起こした際に、
他に待機中のスレッドがあるかどうかで処理を変えたいと思っています。
以上、よろしくお願いします。
89 :
デフォルトの名無しさん:04/12/09 23:08:15
OpenGLでパーティクルとばしたいのだがどうすればよいのでしょう?
>>88 pthread_*にはないので、その辺のロジックは自分で書く。
C言語(Solaris)でマルチスレッド初心者向けの本が欲しいのですが、お勧めを教えて下さい。
英語ならテンプレにあるよ。
ありがとうございます。でも、出来れば日本語がいいんですけど・・・
両方ともいい本だ。こういうしっかりした内容のスレッド本は珍しい。
前の本は古いSolairs独自のスレッドAPI。しかし解説が良い。
初心者向けのスレッド概念、マルチスレッド技法から説き明かしてある。
Solarisは8辺りからスレッド内部が結構変っているから、
細かい制御をしたい人は、
>>3のSunのPDFを。
96 :
デフォルトの名無しさん:04/12/11 16:26:49
fiberってWinMeじゃ動かんの?
CreateFiberは98/Meも使えるようだけど。
>>97 ありがd
あちこち調べまわった結果、95以外は一応大丈夫みたいですのう。
でもfiber関連はドキュメント見ると
> Windows NT: 3.51 SP3 以降を使います。
> Windows: サポートされていません。
と書いてあるのが激しく不安
>>98 Microsoft Platform SDK February 2003から
Client: Included in Windows XP, Windows 2000 Professional, Windows NT Workstation 3.51 SP3 and later, Windows Me, and Windows 98.
100 :
91:04/12/11 21:40:45
>>94 ありがとうございます。今日、神保町で買ってきました。
三省堂には、なかったので書泉グランデで。
>>88 診断(デバッグ)目的なら、必要な状況は理解できるが
それ以外だとちょっと用途が浮かばない。
だいたい、調べた次の瞬間、待機中のスレッドが待機中かどうかわからんし。
sem_getvalue( )なんかも同じだけどね。
セマフォ値を得たところで、その値を使うころに
値がどうなっているのかわからん。
>>51 MPICHを入れようね。
SSHかRSHを使えるようにしてね。
複数のコンピュータ上にNFSで同じディレクトリを用意しておいてね。
mpicc hoge.c
mpirun a.out
で実行できるよ。
>>90 わかりました。
がんがります。
>>101 まさにその通りで、デバッグ用に使おうと思ってました。
printkでどう表示するか、を分けようと・・・。
仰っている懸念は、設計上回避しているつもりではいます。
一旦あるスレッドがpthread_cond_signalで起こされると、
起こされたスレッドでの処理が終わるまではpthread_cond_signalは
呼ばれないようにはしています。
逆に待機スレッドが増えるという可能性はありますが、待機スレッドが
0か0以外かさえわかればいいので無問題です。
というわけでセマフォを使うことにします。
ありがとうございました。
>>103 表示だけならどうと言うことは無いけど...。
> 一旦あるスレッドがpthread_cond_signalで起こされると、
> 起こされたスレッドでの処理が終わるまではpthread_cond_signalは
> 呼ばれないようにはしています。
スレッドの処理の終了と pthread_cond_signal を呼び出す処理の競合のあたりちと心配。
105 :
デフォルトの名無しさん:04/12/12 19:56:20
pthreadで、あるスレッドが動いているかどうかを調べるにはどうしたらいいのでしょうか。
pthread_createで得られるptherad_tを使って判定する関数がありそうなのですが、
調べたところ見つかりませんでした。
しかし、そんな難しい使い方しなくてもCSP的な簡単な使い方だけですます
のではだめなの?何も複雑にすることないじゃん。
自己解決です。
1.動いているかどうか判定する変数を用意する。
2.pthread_create()の直前にtrueにする。
3.pthread_create()で設定したデストラクタでfalseにする。
>>107 テストした瞬間、どうなっているかわからんがな。
>>107 勝手に自己解決するな!
質問の意味がさっぱりわからん。
pthread_tがあるってことは、それすなわちthreadじゃないのか?
「スレッドが動いている」って何?
犬板で聞けば?
ざっと読んだところ。
主張
・正式な意味でのi386サポートをやめたい
理由
・gcc3.2以降はi386をサポートしていない(i386では動作しない)
・i486以降に限定すれば、速度の面でかなり有利。カーネルも、ユーザアプリも。
・i386とi486以降を個別にサポートするのは時間の無駄だ。
提案(3案)
・i386とi486以降に分けて、それぞれサポートする
・i386アーキを捨てる。i486という名前のアーキを新たに作成する
・i386の名前のまま、実際はi486以降必須にする
てなところか。酔ってるので間違い勘弁。
112 :
105:04/12/15 13:38:53
>>109 まずメインスレッドがありますよね?これをスレッドAとします。
そしてpthread_createで新しいスレッドを作って動かします。これをスレッドBとします。
Bで何か作業をやらせておいて、AではBが終わった瞬間、Bの計算結果を使った処理をします。
ところがBが終わったという判定をする方法がわからないのです。
それからpthread_joinはAの作業が止まってしまうので使えません。
以下のプログラムで、isfinished()という関数がありますが、
このようにスレッド識別子pthread_tを使ってスレッドの終了を判定したいのです。
113 :
デフォルトの名無しさん:04/12/15 13:39:43
int global_value;
/*スレッドB*/
void thfunc(void *dat)
{
/*ここでスレッドBの計算を行う
最終的にglobal_valueに計算結果の値が入る*/
}
/*メイン(スレッドA)*/
int main()
{
pthread_t th;
pthread_create(&th, NULL, thfunc, NULL);
while(1){
/*あるループを伴う作業*/
/*Bで計算が終わったか?*/
if( isfinished(th) ){
/*global_valueを使う*/
}
}
return 0;
}
114 :
デフォルトの名無しさん:04/12/15 13:49:34
isfinished()は架空の関数です。これに類する関数があると思うのですが、
pthreadのリファレンスには載っていませんでした。
もしjavaが分かるようでしたら、スレッドクラスのisAlive()と同じものと思ってください。
あるいはjavaの場合はjoin()する際タイムアウト時間が設定できるので、
もしCでもそのような方法があるようでしたら、教えてください。
115 :
デフォルトの名無しさん:04/12/16 02:44:40
某サイトでWinSockでサーバーを作る方法について勉強していたら、
「GUI アプリケーションの場合は、プロセスの主スレッドで呼び出さないようにしてください」
と書いてあったのですが、
これはスレッドを作ってそこでやればいいということですか?
GUIが固まってWindowが再描画されなかったりしても良いなら
単一スレッド上でブロッキングソケットを使っても構わないよ。
そう。非同期などもあるが。
>>116,
>>117 ありがとうございます。
別のスレッド作ってやらないとCUIが固まるんですね。
>>118 Windowsの仕組みを見てみることをお勧めする。
誰がウィンドうを描画してるのか、メッセージキューなどがキーワード
>>119 サーバーとして待機するときにacceptを使った瞬間、
アクセスがあるまで次に進まないので、
ウィンドウプロシージャに送られてくるメッセージなんかも
たまる一方で処理できないということですね?
それでよろし
せっかく説明したのに誰も答えてくれない
(´・ω・`)ショボーン
>>122 その処理なら condition variable を使えばいいんじゃないの?
なんでわざわざ thread の生存で判断したいのかわからん。
んー、重要なのは、
「別のスレッドが終了したこと」ではなく、
「別のスレッドで行っている処理が終了したこと」なんでしょ?
だったら、自分で書いたようなフラグを使っての判定で良いと思うんだけど。
pthread_cond_timedwaitって秒単位、しかも絶対時刻かよ
ダセエな
は? 第三引数はstruct timespec*なわけだが。
>>125 An absolute time measure was chosen
for specifying the timeout parameter for two reasons.
First, a relative time measure can be easily implemented
on top of a function that specifies absolute time,
but there is a race condition associated with specifying an absolute timeout
on top of a function that specifies relative timeouts.
If the thread is preempted between the first statement and the last statement,
the thread blocks for too long.
Blocking, however, is irrelevant if an absolute timeout is used.
An absolute timeout also need not be recomputed if it is used multiple times in a loop,
such as that enclosing a condition wait.
英語なので翻訳します。(要約しながら)
「マニュアル読め」
驚愕に値するマヌケ野郎だな
俺の感覚からすれば、今のケースに「マヌケ」ってのは
どうもしっくりこない。
マヌケ野郎ならなおさら。
なんでだろ
ノータリンならばよろしいか。
うすら間抜けがMT-Safe。
134 :
デフォルトの名無しさん:04/12/22 19:31:23
マルチスレッドって難しいな。
whileの無限ループが入ったスレッドを二つ立ち上げるだけで一気にCPU使用率が100%いく。
一つ目ならまだなんとか20%台なんだが。
スレッドってこんなものなのか?
そんなもんです。
そりゃビジーループを動かしゃそうなる。
一つで20%しか食わないって方がOSのスケジューラに問題ありそうな。
キャッシュ溢れなんじゃね?
139 :
134:04/12/23 18:49:07
>>137-
>>138 どうも。
それから、
同じスレッドを複数呼び出したりしたら、そのスレッド内のローカル変数はどうなりますか?
例えば、 a という数値型変数をローカル変数として宣言してあって、
そのスレッド内で一定時間おきに a の値を一つずつ増やしていく・・・
ということをした場合、このスレッドを2つ3つと走らせた場合に
a の値は・・・?
2倍、3倍になりますか?
それとも各々のスレッド内で独立した変数として通常通り一つずつ増えていきますか?
Cの場合、static変数は全関数呼び出しインスタンスで共通(共有)、
auto変数は全関数呼び出しインスタンスで別個。
>>140 えっと・・・
ということは、staticをつけずに宣言した場合は別々ということですね。
ありがとうございます。
142 :
デフォルトの名無しさん:04/12/23 21:45:29
>>134 ビジーループには0.1秒、または0.05秒Sleepを置くのが常套手段
143 :
デフォルトの名無しさん:04/12/24 19:21:41
recvfromしてるスレッドを停めるとき
もっともスマートあるいはエレガントで
標準的な方法は?
lockを使った排他による停止。
socketをclose
psしてkill
syncしてsyncしてsyncしてhalt
148 :
デフォルトの名無しさん:04/12/24 20:30:32
アアナルほど。
失敗終了させればいいのか。
終了フラグ立ててダミーパケットを送ってみたりしてたんだが、
何か随分無駄っぽい気がしてたんだよな。
「パケットとりこぼしたらやだな」ってのもあったし。
最初、終了フラグに揮発性を設定し忘れてたし。
pthread_kill()でEINTRを起こす。
>同じスレッドを複数呼び出したりしたら、そのスレッド内のローカル変数はどうなりますか?
>例えば、 a という数値型変数をローカル変数として宣言してあって、
>そのスレッド内で一定時間おきに a の値を一つずつ増やしていく・・・
>ということをした場合、このスレッドを2つ3つと走らせた場合に
>a の値は・・・?
すいません、139じゃないんですけど、ちょうど悩んでたんで便乗でおしえてください。
上記の139さんの質問、Cの場合は答えて頂いてますが、Delphiだとどうなるでしょうか?
さらに上の例で言うと、aがローカルではなく、スレッドのpublicなメンバーだったらどうなるでしょうか?
「スレッドのpublicなメンバー」って何やねん。
>>151 TThreadから派生させて作ったクラスのpublicメンバ変数ってことです。
こんな感じ。
type
TMyThread = class(TThread)
private
{ Private 宣言 }
public
a: integer;
protected
procedure Execute; override;
end;
Delphi付属のサンプルコードに、スレッドを複数立ち上げてソートするコードなかったか?
すんません、6Personalなんですが、サンプルコードついてないっぽいです...
scheme(scm)でスレッドを実装したいときはどうすればいいのですか?
make-engineがそれにあたるのでしょうか…
>>156 回答ありがとう。
しかし...グローバルと一緒ですか...
Priveteならたぶんスレッド内で独立した変数になるんだろうけど、メインのフォーム
から操作する必要あるんですよねえ。
publicな手続きつくってその中でaを操作すればいいのかな。
>>157 御免、言っている意味がよくわからない。
スレッドローカルな変数で、グローバル変数とローカルな変数の中間。
生存期間: そのスレッドが終了すると(TThreadが消えると)なくなります。
アクセス: パブリックなので、アドレス分かればどこからでもアクセス可能。
で、スレッド毎に確保。
そのスレッドから見ればグローバル変数と一緒。
なるほど、スレッドローカルな変数ですね。説明ありがとう。
僕も最初そうかと思ったんですけど、実際に動かして見るとどうも動きがちがうのよねえ。
152であげた例でいうと、メインフォームのほうでこいつのインスタンスを二つ作って
Thread1:=TMyThread.Create(False);
Thread2:=TMyThread.Create(False);
でaを操作する。
Thread1.a:=1;
TMyThreadのExecuteでaを監視してるんですが、これやると、なぜかThread2も
反応してしまうんですよ...
どこが間違ってるんでしょうか。ご指導お願い致します
TMyThread のインスタンスはメインスレッドでつくられるんだから、単なるフィールド変数だろ
これデルファイ?C++ならメモリアドレス見れば一発なのに
>>160 スレッドローカルだからでは?
もう自分でも何をしたいのか、よくわかっていないでしょ?
皆さんコメント感謝
163さん言うとおり、相当煮詰まってあれこれ試しているうちに
何がなんだか混乱していたのも事実です。
aをpriveteに移して、aをメインスレッド側からいじらないように改造
したら誤動作なくなりました。
正直言うとまだ明確にはわかっていません。
あまりプログラミングの知識ないのですが、最初ごく単純なツール
の予定だったので私でもできるかなと引き受けたのですが、あれよ
あれよと機能追加要求が来て大変です。
でもまあ、あれこれ迷いながら楽しんで仕事できてます。
とりあえず変数の種類とスコープを復習しなおすことにします。
ありがとう。
超高速で操作するとなんかスタックが壊れる・・・
「無効なアンワインド対象がアンワインド操作で検出されました。。」
ってなんやねんわけわかめ!わけわか!
スタック壊れてるのはたいてい自分でメモリを壊してるせい
>>165 「アンワインド」の意味は分かっているの?
スタック上のアンワインド用のメタデータが壊れているんでしょう。
それが餡ワイン度している時に見つかったと。
うへぇ、不味そう<餡ワイン
クリティカルセクションオブジェクトのLockCountが-1でOwningThreadもNULLで
どこもロックしてないのにLockSemaphoreだけロックされててわけわかめ。なんじゃこれ
もう疲れた
170 :
デフォルトの名無しさん:05/01/23 22:50:00
スレッドの生成や消滅って、implicitなmemory barrierになると考えて良いのでしょうか?
#POSIX, Win32両方使ってます。
状況がつかめん。
コードで示せ。
172 :
170:05/01/24 14:58:01
メインスレッドが大域変数gFooに1を、排他制御なしで書く
↓
メインスレッドがスレッドTを生成する
↓
TがgFooの値を排他制御なしで読む
の順で処理が発生したとき、Tが観測するgFooの値が1であることが保証されているかが知りたいです。
メインスレッドは1を書いた後、当面gFooにアクセスしないと仮定してOKです。
よろしくおながいします。
>>172 環境によっては保証されない。
何故ならば、大域変数へのアクセス完了を待ってスレッド生成する保証がないから。
174 :
170:05/01/24 18:28:24
>>173 > 環境によっては保証されない。
> 何故ならば、大域変数へのアクセス完了を待ってスレッド生成する保証がないから。
gFoo = 1;
// ここ
pthread_create();
というコードで、「ここ」と書いたところはsequence pointで、かつ「ここ」ではまだシングルスレッド
状態なわけですが、それでも「大域変数へのアクセス完了を待つ」が保証されないのでしょうか?
>> スレッドの生成や消滅って、implicitなmemory barrierになると考えて良いのでしょうか?
という質問に戻ってしまうわけですが・・。
175 :
デフォルトの名無しさん:05/01/24 18:52:29
そのコードなら確実に1は保証されるぞ。
1の代入が完了しなければスレッドが作られないんだから。
1の代入とスレッド作成は同一スレッドで行われるわけだからね。
アセンブラのレベルで、同一スレッドでmov命令(1代入)発行した後に関数コール(pthread_create)
する場合でも、movが完了する前にpthread_createされることって有り得るの?
そういう話ではないよね?コンパイラのオプティマイザによって変わってくるということかね?
Pentium4とかの最近のCPUだと有り得る
コンパイラのオプティマイズ(命令のreorder)の話もあるけど、それに加えて、
・コンパイラがreorderしなくても、CPU(H/W)が命令をreorderするかもしれない
・あるCPUでmovが完了したからといって、その値が別のCPUから観測可能かはわからない
ということでは?
どうも。勉強不足でした。恥ずかしい。
前スレッドを見たいが見られない。困った。
>>180 memory barrierでググればそれ関係の論議は大抵見つけられると思う。
182 :
170:05/01/24 19:33:12
pthread_createやCreateThreadの先頭にmemory barrier(full fence)が挿入され
ているのか、挿入するよう規格が要請しているかが知りたいです。
#またはfenceなどなくても大丈夫というならその理由を
volatile
またvolatile厨か・・・
total store order
またtotal store order厨か・・・
どうでもいいじゃん
スレッドセーフなライブラリつかっとけばOK
190 :
170:05/01/24 21:39:43
>>185 > total store order
すみません、memory modeに疎く、TSOだけだとちょっと意図が汲めません。結局
>>172の例は
safe/unsafeどちらだとお考えでしょうか?
mode -> model
>>170 volatile とか VC/VC++ の _ReadWriteBarrier とかその辺の問題はともかく、
MSのサンプルでも、Win32のThreadProcで、渡されたデータ、実体はポインタ、
が挿すメモリアクセスするような場合にMemoryBarrier()呼び出しをしている例は
一度も見たことなく、逆の例は沢山あるので、
Win32のCreateThreadはメモリバリアになってるような気がします。
具体的なドキュメント等の記述は見つからないけど。
↑
編集していたらなんか「、」が多くて変な文になってしまった。
この名前空間、クラス、およびメンバは、.NET Framework Version 1.1 だけでサポートされています。
>>192, 195
ありがとうございます!!
スッキリ解決です。
このスレでvolatileって言葉が出てきたらほぼ100%厨房な間違いってことでFA。
volatileはthreadじゃなくてinterruptのときのモノだしな。
またvolatile厨か・・・
>199
ISO C/C++的にはシグナルハンドラからアトミックに更新したい変数に用いる型、だね。
volatile sig_atomic_t。この使い方以外でvolatileって語は出てこないし。
あーあと、POSIXにはまったく登場しないね。
202 :
デフォルトの名無しさん:05/01/26 00:36:59
>>198 56はリア厨だったりする罠。
>通常、小さい変数などはvolatileをつけるべきだってのは知っているのですが、
必要ありません。
>const_castでvolatileを変える仕様はMS VC7.1には入っていないし、
>同期をかけるクラスはすべてvolatile版も作れということですかねぇ。
CRITICAL_SECTION使え
203 :
デフォルトの名無しさん:05/01/26 14:01:57
またvolatile厨か・・・
またvolatile厨か・・・
またvolatile厨か・・・
またvolatile厨ですね・・・
(またvolatile厨)厨ですよ・・・
((またvolatile厨)厨)厨ですよ・・・
こんな(((volatile厨)厨)厨)厨見たことない・・・
こんなところで三段落ちを見るとは…さすがvolatile厨だな
来たれ、void厨!
ということにしたいのですね。
>>213 condition variableで待つ場合ロックしているmutexを一時的に
解放してくれて、かつ、signalやbroadcastで条件が調った時に
一時的に解放していたmutexを自動的にロックしてくれる。
なので、時間とかの問題ではなく、デッドロックを避けつつ、
必要な排他処理を過不足無く行なうために必要であれば、
condition variableを使うか、自前で同等の処理を行なうことに
なる。
mutexをロックしたまま別のmutex待ちをして良いのなら、
condition variableを使う必要は無い。
>>214 どうもありがとうございます。
自分が考えていたのは、mutex が一時的に解放されてもそれほど嬉しく無さそうな
処理だったので、まずは mutex のみで実装してみようと思います。
volavolavolavolavolavolavolavolavolavolaァァァァーー!
217 :
デフォルトの名無しさん:05/01/30 18:28:51
intサイズ以下なら、volatileつければ、
マルチスレッドのときにも排他は不要ですよね?
そうですね
CCSを使ってモデル化して検証する
>>217 不要だと思うなら、そうすればいい。
後で泣きを見ても知らんけどな。
>>221 100%煽りでしょ。
せっかくの「またvolatile厨か・・・」への前振りを無駄にするな。
またvolatile厨か・・・
またvolatile厨厨か・・・
心配しないでもI/Oの方が遅い。
stringstreamの場合は工夫した方がいいと思うが。
クリティカルセクションならカーネルレベルまで話が及ばない(ほとんどのばあい)
から重くないと思われ。
どっちもI/Oの重さを考えたら無いようなもん。
応答性やパフォーマンスを気にするならcoutなんかやめて
非ブロッキングI/Oを使えばいい。
229 :
デフォルトの名無しさん:05/02/03 10:36:44
キタ━━━━(゚∀゚)━━━━!! @cppll ML
>επιστημηです。
>
>で、関連事項なんすけど、スレッド間で共有する変数の類は
>Mutexなんかでガードしてないならvolatileつけとくのが無難
>なんでしょかしらやっぱ?
えぴすさんでもひっかかっちゃうのね。
>>229 「でも」とはなんだ「でも」とは!
奴だからこそ、だろう。
レスはもっと香ばしいけどね。レジスタがどーたらとか。
>>229の文章ならそんな問題ないでしょう?
排他のためにやるわけじゃなくて、
最適化の抑止の事だけを話しているのかも知れないから。
十分って言っているわけじゃなくて、無難だしね。まあ、
>で、関連事項なんすけど、
何に関連していたかにも依るわけですが…
constと同じとこにvolatileやconst volatileも書けるっていうお話でしたとさ。
>>232 > 排他のためにやるわけじゃなくて、
> 最適化の抑止の事だけを話しているのかも知れないから。
排他が関係しないスレッド間の共有って、全スレッドがreadしかしないとかそういうこと?
確かにそれなら定数読むのとかわらんから、volatileもメモリバリアもいらないけど、そういう文脈なのかなぁ。
しかし、最近そこかしこでmutexのかわりに/mutexに加えてvolatileって騒いでる人を見かけるんだけど
国内でだれかvolatileを布教してる人でもいるんですか?
またvolatile厨厨か・・・
>>237 思い込みはどうでもいいからベンチマークとれよ
239 :
デフォルトの名無しさん:05/02/04 09:00:25
スレッドプログラミング初心者です。
volatileはマルチスレッド対応ですか?教えてください。
アプリケーションがシングルスレッドである間しか書き込みしない事が分かっている場合
(スレッドが2つ以上になった時点では読込しか行わない場合)
排他処理したり、volatile修飾する必要は無いの?
>>241 またvola (ry
えーとね、排他は必要ない。169-170の質問と実は同じ内容だから、
回答は
>>192 >>195 を参照のこと。
あと、volatileはいい加減やめい。スレッドとvolatileは無関係。
ボラボラボラボラボラボラボラボラボラタイール!
volatileってコンパイラの想定外の理由で変数の内容が変わるので最適化の対象にしないでくれって宣言だよね?
bool型の値に書込と読込を色々なスレッドから同時にするような場合排他をしない場合は、
trueに変えたはずなのにまだfalseと読み出されたりするくらいで、
いきなりスレッドが死んだりする事は無いよね?
>>245 お前がな。
そもそもこのスレでのvolatile発言はすべて煽り。ほいほい釣られるのはやめてくれ。
>>247 お前がな。
そもそもこのスレでのvolatile発言はすべて煽り。ほいほい釣られるのはやめてくれ。
volatileにしてから、女の子にもてもてです。
250 :
デフォルトの名無しさん:05/02/05 02:14:05
>>246 volatileと宣言すれば完璧です。
volatileって飛びますよね
252 :
デフォルトの名無しさん:05/02/05 15:08:47
volatileほいほい状態のなか申し訳がないのだが、c/c++のvolatileと
java/c#のvolatileは意味合いが違うという理解でいいのでしょうか?
普通のブラウザからなので過去スレッドに既出ならすまそ。
同じ
>>252 c/c++の言語仕様にはマルチスレッドとvolatileとの関係なんて定義されていない。
きちんと定義されているものと未定義のものとを比較して、
意味合いが違うとかどうとか言うのは意味がない。
bool f;//global
while (f)
{
;
}
は最適化で
if (f)
{
for(;;) {}
}
になったりはしないの?
>>256 ノ
コンパイル時の最適化についての話でしょう。
前者の記法は後者の記法のように変換されて解釈されるのではないか、
という質問だと思います。
>>254 >c/c++の言語仕様にはマルチスレッドとvolatileとの関係なんて定義されていない。
ありがとう。なんかすごく腑に落ちました。
現実には独自仕様などでそれなりの関係で動いちゃう処理系が多々あるってことで
しょうね。混乱するほうが自然なような気もしてきました。
>>257 今でも最適化でこんな間違いが生じる恐れあるのか?
int f = 1;
while (f) {
/* ループ中でfは参照されない */
}
こういうコードなら、それに近い最適化される
可能性もあるんじゃない?
ていうかね、例えば
void f(const char *str) {
int i;
for (i = 0; i < strlen(str); ++i) {
...
}
}
なんてコードは、
慣れてる人が見れば「毎回長さを判定している糞コード」なわけだけど
VCとかだと、このstrlenをループの外に出しちゃうわけよ。
こういう最適化をするコンパイラが
ループ内で変更していない変数の値を、ループ時に毎回評価するなんてありえないわけで。
262 :
デフォルトの名無しさん:05/02/05 20:51:20
> VCとかだと、このstrlenをループの外に出しちゃうわけよ。
はつみみです
>>262 VCについては知らんが、gccだとpureアトリビュートってのを
関数に宣言してやると、そういう動作をするな。
以下、Infoより引用。
---
`pure'
Many functions have no effects except the return value and their
return value depends only on the parameters and/or global
variables. Such a function can be subject to common subexpression
elimination and loop optimization just as an arithmetic operator
would be. These functions should be declared with the attribute
`pure'.
>>264 pureって意味わかりにくね?
C++の純粋仮想関数を想像しちまう。
Oracle PL/SQLのdeterministicの方がいいな。
結局どうなんですか?
268 :
デフォルトの名無しさん:05/02/06 09:14:47
volatileとつければ完璧です。
volatile相談室に改名したら?
volavolavolavolavolavolavolavolavolavolaァァァァーー!
ごまかして終わりですか?しょせん2chですもんね。
volatile宣言はコンパイラの吐くコードの最適化を抑制します。
そのことと、マルチスレッドプログラミングがどう絡むのかというと、
最適化を抑制することが、
マルチスレッドプログラミングにおいて発生する問題を解決したり、
未然に防いだりするのに有効な場合があるのです。
もちろん、volatileの使用は、起こりうる問題の全てを解決したり、
予防したりするものではありません。そとのきは、
mutexを使うなりして別の手段を用いる必要があるでしょう。
そとのときは...云々は、
そのときは の誤りです。スレを汚してごめんなさい。
そとのときはそのときはのあやまりですはそとのきはそのときはのあやまりですのあやまりです
早口言葉?ちょっと笑えた。
あ...
誤)そとのとき
正)そのとき
ではなくて、
誤)そとのき
正)そのとき
だと指摘してるのかな?
2重にスレを汚してごめんなさい。
ま た v o l a 厨 か
「場合がある」程度で使われちゃ迷惑なんだよ
つか仕組を理解していない証拠だ
だーかーらー、volatileとmulti-threadは関係無いっての。
マルチスレッドでの同期とはアクセスタイミングの問題ではないから、
volatileは何の解決にもならないんだよ。
volatileで解決したように見えるものを別のところに持っていって正しく
動く保証は全くない。
自説に固執する前にちっとは勉強したらどうよ。
言語の規格で定められていない以上,VC++で動いたからって,
他の環境でも正常に動作するとは限らないというのは全く同意です.
正直にいうと,マルチスレッドプログラミングはWindows上でしか
経験がありません.それで,
>> 自説に固執する前にちっとは勉強したらどうよ。
自説に固執しているつもりもありませんが,
勉強する意欲はありますので,よろしければ,
>> volatileは何の解決にもならないんだよ。
ということを学習できる書籍,URLなどをご紹介ください.
英語でもかまいません.
Memory Mapped I/O 以外に volatile を使う必然性が解らん…
Atomic じゃない処理でアクセスしてるなら、気休めにもならんぞ。
>>283 > Memory Mapped I/O 以外に volatile を使う必然性が解らん…
> Atomic じゃない処理でアクセスしてるなら、気休めにもならんぞ。
cppllの受け売り?mmapでもvolatileはまずい。
あ...私もところかまわずvolatile使いまくってるわけじゃないです.
例えば,
bool 型の変数(初期値false)があって,ある一つのスレッドが,
その値をtrueに変更し,他のスレッドは,その変数の値が
trueになるのを待ち構えている...的な状況に使っています.
同期オブジェクト使えばいいじゃん.と思われるかもしれませんが,
例えば,上のbool型の変数がグローバル変数であった場合,
単純に同期オブジェクトに置き換えることも出来ません.
初期化の問題もあるし,それをクリアしてもリソースをいつ
OSに返せばいいかという問題もあります.
より具体的には,
http://www-6.ibm.com/jp/developerworks/java/040416/j_j-jtp02244.html の後半にある,
「リスト1. volatileフィールドを「見張り」変数として使う」
的な利用の仕方をしています.
上記サイトは言語がjavaですし,古いjavaのメモリ・モデルでは,
最適化のリオーダの定義が甘く,うまく動かないと結論づけらているので,
あんまり適切なソースではありませんが,私が提示できるのはこれくらいです.
>>280 such as interrupt handlers.
でしょ?MSもスレッドとの相互作用は言及していないやん。
まだ言語の規格うんぬん言ってるよこの人……。
ソースコード中にvolatileなんてDOS時代で割り込み使うときに書いただけだな。
>>285 変数の操作前後に同期オブジェクト使用。
>>285 > 例えば,
> bool 型の変数(初期値false)があって,ある一つのスレッドが,
> その値をtrueに変更し,他のスレッドは,その変数の値が
> trueになるのを待ち構えている...的な状況に使っています.
バカの典型例。
> 同期オブジェクト使えばいいじゃん.と思われるかもしれませんが,
いいじゃん、じゃなくてそれが正しい解。
> 例えば,上のbool型の変数がグローバル変数であった場合,
> 単純に同期オブジェクトに置き換えることも出来ません.
> 初期化の問題もあるし,それをクリアしてもリソースをいつ
> OSに返せばいいかという問題もあります.
単なる言い訳。
>>284 cppll ってのが何か知らんが、Mapped Memory の話なぞしていない。
メモリ空間に配置された I/O ポートの話。
>>285 うむ。最悪な用途だな。
>同期オブジェクト使えばいいじゃん.と思われるかもしれませんが,
使えばいいじゃん。
>>288 ソースの提示ありがとうございます.
早速読んでみます.
> 残念ながらダメな使用例の典型です。
でも,ちょっとショックです.
285の使用例を許すOS自体が存在しないということなら,さらにショック.
>>292 > でも,ちょっとショックです.
> 285の使用例を許すOS自体が存在しないということなら,さらにショック.
OSっつーかハードウェアとコンパイラね。
(1)シングルコアのシングルCPUの上でしか動かさないプログラムか、
マルチプロセッサだけど強いmemory consistencyを持つハードウェア上でしか動かさないプログラムで、
かつ、
(2)コンパイラの最適化の特徴を完璧に把握している
場合のみboolをロックなしで使用してよし。実質的に常人には判断不可能とおもうが。
特に(2)はコンパイラの作者でもなければわからない悪寒。
>>293 解説ありがとうございます.
pdf,まだ読んでませんが,困難さが伝わってきました.
285のような場合は,Windowsの場合ですと,
boolをlongにして,InterlockedExchangeみたいな
API を使っても無駄なあがきでしょうか?
固執しまくってるやん。
>>285 の“trueになるのを待ち構えている”が
ビジーループだったりすると、volatile 以前の問題だったり。
>>294 InterlockedXXXはもちろんOKでそ。
基本的にはマルチプロセッサを考えない場合にはスレッド間でのメモリ内容の
同期化は考えなくても良いので、volatile とか _ReadWriteBarriar (VCね)とかで
テキトーに済ませてしまっても問題ない。
でも今時「マルチプロセッサではデッドロック起こします」なんてプログラムは
書かないことが多いんでは?なので他のスレッドが書いたデータを読むとき
には、適当にメモリバリアになる処理を入れておくべき(ドライバ書いているとき
には、リングバッファ - メモリモデルの問題さえなければ、writerとreaderは
並行して動作しうる - とかではまることがある)。
あとJava VMの場合は新し目のJSR-000133 に準拠したものだと、
同じvolatile変数へアクセスするコンテキスト間ではアクセス時点で同期化が
成されるみたいだけど、これはまだ一般的じゃないと思う。
299 :
デフォルトの名無しさん:05/02/08 13:56:34
>>298 コンパイラの最適化によるトラブル@シングルプロセッサは無視ですか?
変数の領域が最適化によってレジスタに作られた場合、別のスレッドがこれを参照することの影響ってあるんですか?
>>300 そのためのvolatileでしょうが。
#って書くとまたvolatile厨云々書く香具師が沸くのかな?
>>302 外から参照できるような変数がレジスタに割り付けられるような
間抜けなコンパイラが存在するんですか?そりゃすげぇや。
305 :
デフォルトの名無しさん:05/02/08 16:56:01
>>304 C/C++ではvolatileでメモリへの割付は強制できるけど、Javaとは違って当該のメモリ位置に
何時データを書き出すかまでは指定できない(読み出しは字面上の位置でメモリから読むこと、
と規定されてるけど)。
んだからさんざ既出の様に「VCの_ReadWriteBarrierみたいなもの」を併用する必要があるわけ。
gccでもvolatile変数に代入した後インラインアセンブラでちょいと参照しておけばOKなんじゃない?
(でもgccってgasにした後で最適化入るんだったような記憶が・・・それだとダメか?)
邪魔が入ってpdf読めないでいるうちに重要な投稿がいくつも...
実は,Javaにおけるクラスレベルのロック機能みたいなのを実現したいと思っているのです(とりあえずはWindowsで,言語はC++).
クラスレベルのロックをするための同期オブジェクトは,初期化と後始末の問題があるため単純に静的な変数に出来ません.
また,クラスレベルのロックをするための同期オブジェクトの生成過程もロックしないといけませんし,
それをするのにmutexなどの同期オブジェクトを作っていたのでは,またそのオブジェクトの生成過程をロックしなければいけなくなってきりがないのです.
そこで,volatileと,Interlock系のAPIを使用してクラスレベルのロックをするための同期オブジェクトの生成過程をロックすればよいんでは?
と思いプログラミングしてみたところ,見た目は動いてるっぽいです.
ただ,動作確認をしているマシンが1CPUですので,まだまだ,勉強が必要です.
とりあえずは,今回提示されたpdfを読んでみようと思います.
勉強になりました.ありがとうございました.
>>303 いや、だからね、
> 同期化は考えなくても良いので、volatile とか _ReadWriteBarriar (VCね)とかで
> テキトーに済ませてしまっても問題ない。
「volatileとか」は余計だろ?
メモリバリアを正しく使ったなら無問題だよ。
>>306 > gccでもvolatile変数に代入した後インラインアセンブラでちょいと参照しておけばOKなんじゃない?
参照っていうか、fence命令を挿入だな。Linuxカーネルなんかに_ReadWriteBarriar相当の
マクロなんかがあるから参考にすればいい。
310 :
デフォルトの名無しさん:05/02/08 18:23:28
>>302 > そのためのvolatileでしょうが。
全然違う。
volatileによって、
変数の領域が最適化によってレジスタに作られた場合、*自スレッドが* これを参照することの影響を排除すること
はできるが。
>>283 > Atomic じゃない処理でアクセスしてるなら、気休めにもならんぞ。
アトミックかどうかは関係ないでしょう
>>308 308で言ってることは正しい指摘だと思うんだけど、それはともかくとして
>>298 >コンパイラの最適化によるトラブル@シングルプロセッサは無視ですか?
これの例を聞いてみたわけだけど。エイリアス関係ならvolatile指定でOKだし・・・
>>312 IA32の強めの一貫性を仮定しているんだろうね
>>313 ↑読み返すと粘着っぽいので反省して取り下げます・・・
>>313 俺に聞かれても困るんだけど・・
volatileはvolatileで修飾した変数Vをレジスタに置かないことは保証するが、V
にアクセスする順序(Vにアクセスしたことが他CPUからみえるようになるタイミ
ング)までは制限しない
ということじゃないの?それ以上はEffectiveC++の作者様にでも聞いてくれろ
> volatileで修飾した変数Vをレジスタに置かないことは保証する
これまた微妙な表現・・・
>>317 参照する場合には、ってことだよね・・・
あと他人の質問に一旦返事しといて、再度聞かれると
「俺に聞かれても困るんだけど・・ 」は反則じゃねーの。
「volatileとmulti threadはまったく無関係」というレスが沢山つくのを見ながら
「このスレッドの人はJSR-133も知らないのか」と思っていたが、みんな
知ってて遊んでたのね。人が悪い。
>>319 全員Cの話をしているものだとばっかり。
321 :
デフォルトの名無しさん:05/02/08 20:26:43
>>307 WindowsにゃPTHREAD_MUTEX_INITIALIZERみたいなのがないからなぁ。
苦労するのはよくわかる。まぁ、、現実にはみなテキトーにやってるわけだがw
>>307 漏れはヘルパクラスを作って静的変数(classのstaticメンバにすることが多い)の
コンストラクタとデストラクタでやってます。
複数のスレッドから、DLL等ダイナミックにローディングされるような状況(COM等)ではそれだと
上手くないので、DLL_PROCESS_ATTACH のタイミングでCRITICAL_SECTIONを初期化し、
開放はしないという方針(DLL_PROCESS_DETACHでDeleteCriticalSectionはGPF出ることがある)。
Mutex使えば簡単なんだけど、重いからなぁ・・・
> 静的変数(classのstaticメンバにすることが多い)
初期化順の問題がおきそうですね。
あと、Windowsってmain関数が走る前にマルチスレッド状態ってことはあるんですか?
>>324 初期化順の問題が出てくるようなコードの場合には、DllMainで処理するより他ないでしょうね。
>あと、Windowsってmain関数が走る前にマルチスレッド状態ってことはあるんですか?
そういうプログラムを作るか、他プロセスからフック等で介入するかすれば。
J・S・R! J・S・R!
ま、マルチスレッドといえばJavaの話題と考えるのが自然なわけだが。
複数枚CPUのささったサーバ等で、Javaでマルチスレッド化
されたアプリを動かしたとき、そのアプリ内でたてるスレッドって
それぞれ別CPUが処理してくれるのでしょうか?
いや、単純にスレッドをCPU分作れば複数枚のCPUパワーを
フルに使えるのか、それともシングルスレッドのアプリを複数
プロセス立ち上げた方がいいのかってところなんですが。
もちろん完全並列処理が可能だという前提で。
VM次第。
OSとJVMの実装による。
SunのJREとSolaris/Linux/Windowsなら基本的にはその通り。
並列度がどれくらい効くかはOS自身の成熟度にもよるけど。
あとはプロセスを別個に作るとかなりメモリが無駄に重複して
消費されるだろうとかGC的には逆に並列でスレッドが沢山走って
でかいプロセスだと負担がどうだろうとかその他のリソースの
制約はどうだろうとかあるけど。
HTMLのセレクトボックスの項目をデータベースから持ってきた値にしたいんですけどうまくいきません。
どうしたらいいんでしょうか?
真剣にだれか教えてください
ありがとう。
なんスレッドくらいがよいのか試してみます。
いい感じの内容の論文(なのかな?テクニカルレポート?)でした.
内容をちょっとだけ紹介します.
Singletonクラスのインターフェースが次のように定義されていたとします.
class Singleton {
public:
static Singleton* instance();
...
private:
static Singleton* pInstance;
};
本当はいろいろな場合わけがなされているのですが,ここでは,
Double-Checked Locking Pattern(DCLP)としてのinstanceメソッドの(まずい)実装例を取り上げてみます.
Singleton* Singleton::instance() {
if (pInstance == 0) { // 1st test
Lock lock;
if (pInstance == 0) { // 2nd test
pInstance = new Singleton;
}
}
return pInstance;
}
これが何故まずいのかというと,
pInstance = new Singleton;
この一文がアトミックに行えないことにその原因があります.
【次へつづく】
本文では上記コードを下記の等価なコードに置き換えて説明しています(Step1〜3の順番がややこしくなっていから注意して).
Singleton* Singleton::instance() {
if (pInstance == 0) {
Lock lock;
if (pInstance == 0) {
pInstance = // Step 3
operator new(sizeof(Singleton)); // Step 1
new (pInstance) Singleton; // Step 2
}
}
return pInstance;
}
で,どんな問題が起きるかというと,
1.Step2のコンストラクタが例外を投げた場合,pInstanceにはoperator newでアロケートした領域のアドレスが代入されたままになります.
さらに,コンストラクタが例外を投げたときは,operator deleteが呼ばれてしまうので,pInstanceにはフリーストアに戻ってしまった記憶領域のアドレスが保持されていることになります.
2.Thread Aがinstanceの中に入ってif文を通過しロックを取得し,Step3とStep1 を実行したとします.そしてThread Aがサスペンドしたとします.
pInstanceにはnullではないポインターが保持されていますが,コンストラクタはコールされていません.
この状態でThread Bがinstanceの中に入ってきた場合,pInstanceはnon-nullですから,そのまま,pInstanceの値をリターンしてしまいます.
何度もいうようですがコンストラクタはコールされていません.
正直,ここまで考えるか!と感心してしまいます.しかもこんなのが連続します.
Singletonクラスを設計するときにはとても役立ちそうです.
ありがとうございました.
http://www.cuj.com/documents/s=7998/cujcexp1902alexandr/ で 285 的なvolatileの使用例があります.上記urlでは,最初に問題のあるコーディング例として,
class Gadget
{
public:
void Wait()
{
while (!flag_)
{
Sleep(1000); // sleeps for 1000 milliseconds
}
}
void Wakeup()
{
flag_ = true;
}
...
private:
bool flag_;
};
というコードが記述されています.そして,
So all you have to do to make Gadget's Wait/Wakeup combo work is to qualify flag_ appropriately:
class Gadget
{
public:
... as above ...
private:
volatile bool flag_;
};
と,問題点が修正されます.でも,CPUが複数個の場合は,環境依存ということになりそうですね.
>>338 フラグをヒントにするくらいなら問題ないんじゃね?
終われそうなら終わってくれって程度で。
ああ...確かに.個々のCPUのキャッシュが...どうのこうの考えたのですが,
仮にメモリの内容の同期が遅れてループが多少何回か多めに回転しても,この場合は無問題ですね.
341 :
デフォルトの名無しさん:05/02/09 14:32:29
>>339 いいかもね。
俺のチームからはクビにするけど。
>>341 お前のチームで一緒にやりたくねーよwwww
結局
>>246はどうですか?
>>250さんが言っているように
volatileにしとけば完璧ですか?
>>343 そうだ。その通りだ。わかったらクソして寝てろ。
ときどき聞くけどvolatileなに?
温めるの
>>345 そうだ。その通りだ。わかったらクソして寝てろ。
volatileとマルチスレッドは全く関係ないんだってば
>342
wの多さは知能の低さ
>343
スレッドが死んだりすることはない。volatileで他スレッドの変更を
いつの日か読めるかどうかは環境依存。何度もいうが規格で規定され
ていない(C++)か未定義とされている(POSIX)ことに結論を求めては
いけない。ロック汁。
まぁ釣りなんだろうけどクマー
>>349 規格厨ですか?
Sleep()で寝てもいるのにvolatileなフラグの変更を
いつまで経っても読み取れない処理系挙げてみろよ。
なんでヒントって書いたかわかってないだろ?
Alpha
353 :
デフォルトの名無しさん:05/02/09 22:08:34
>>351 > なんでヒントって書いたかわかってないだろ?
なんで条件変数とかEventオブジェクト使わないの?
>>351 己の無知を棚に上げて人を規格厨呼ばわりするのはやめておけ。
>>355 ふぅん。なら問題の出る処理系挙げてみ?
ここって規格の話をするスレだっけ?
Alpha
>>353 想定したのはProducer/ConsumerのConsumer側スレッドプールの
スレッド数を縮小させる場合などで、ターゲットのスレッドに対して
適当なタイミングで終了させるフラグを実装するような場合。
キューから引っ張ってきたタスクを実行中に止められるはずもなく、
その次のループで確実に終了する必要もない。
この条件でもフラグ見るのに絶対に同期する必要がある?
>>356 池沼が根拠の無い嘘を書き散らす場所でないことだけは確か
351は出荷済みのコードのことを思い出してガクブルしていて
誰かに問題ない!と言ってもらいたいんだろうな。
OSとCPUとコンパイラくらい書けばいいのに。
volatileとマルチスレッドは無関係
んにゃ。別に。
同期しときゃ済む話だし、省いたところでパフォーマンスが特に
上がるわけでもないからどうでもいい。
だけど、更新のある変数を扱う時は*絶*対*に*同期しなきゃ
いけないような論調になってるのが気に食わなかっただけ。
普通はフラグだけで完結するようなものはなくて、厳密な整合性を
必要とする操作のところで同期取ってるはずだから、結局はそこが
Memory Synchronizationになってるから問題ないでしょ?ってことさ。
だから問題がある処理系があるなら、それを挙げろ、と。
363 :
デフォルトの名無しさん:05/02/09 23:09:31
横から失礼。
お前がコード貼って、みんなの環境でコンパイルして逆汗して、それをメモリモデルを考慮しながら検証するしかないだろうな。
俺は嫌だけど。
>>351 C/C++なら、プログラミング言語の処理系レベルの問題ではなく、
アーキテクチャレベルの問題なんだが、それがわかってないようだな。
だからさ、問題のおこる実例を出せって言ってるんだよ。
バカはこれだから困る。
>>366 変数が扱えなくてリンゴとミカンでしか考えられない小学生みたいですね。
>>366 おまいさんの質問に対して、もう二度も例が挙がってる。
それに気付いてない時点で、無知を曝け出しているのだよ。
では、volatileラヴな皆さんへの問題。
// 初期値はともに0とする。
volatile int a = 0;
volatile int b = 0;
int threadA() {
int x;
a = 1;
x = b;
return x;
}
int threadB() {
int x;
b = 1;
x = a;
return x;
}
上のようなC/C++のコードがあったとして、
SMP構成のPentium4マシン(HT機能はoff)上で
threadA(), threadB()をそれぞれ別スレッドから同時に呼び出したとする。
このとき「threadA()とthreadB()がともに0を返す」ようなことが起こり得るか?
起こり得る(起こり得ない)なら、その理由は?
次に、同じプログラムをUP構成だがHT機能を有効にしたPentium4マシンで
動かした場合はどうなるか?
# とりあえず、C/C++コンパイラはgcc 3.xとする。
# (VCでも同じ答えになるはずだが。)
371 :
デフォルトの名無しさん:05/02/10 02:03:47
ようやく楽しげになってきたのでage
うーん、過去ログなどは見てないで書くけど。
>>369はvolatileかどうかに関わらず、どちらが先に実行されるかって問題だけな気がする。
volatileがマルチスレッドに使えるとしている人たちの論拠は、緩やかな同期を取る話であって、
>369みたいなクリティカルな実行順序まで期待しての話じゃないと思うのだけど。
#わーい、自分でも何が言いたいのか判らんぞ
373 :
デフォルトの名無しさん:05/02/10 02:20:37
> SMP構成のPentium4
ハァ?バカか?
んなもん存在しねーよ。
これだからバカは困る。
Pentium4/Xeon
351よ・・・もういい、頼むからもう安らかに眠ってくれ
消えろ。
なんかボラタイルが自動的に同期をとるようにコンパイラに指定する
ものだと思ってるってことになっちゃってない?
>>376 そういうレベルの話はとっくに片付いてる。
雑音も多いけど珍しくまともな議論になっていると思うよ。
ぼらたれば
>>369 volatileで修飾されいるとき、
変数の宣言とreturn文の間の2文の実行順序って気まぐれに変化するんだっけ?
何気に回答になっていなくてすまん。
しまった。x はvolatileでなかったのね。
381 :
デフォルトの名無しさん:05/02/10 11:22:15
誰もコンパイルしないな
ここはコンパイラももってないリア工房のスレだったのか。
環境依存だからコンパイルして動かした所で意味無いしね
383 :
デフォルトの名無しさん:05/02/10 11:28:54
(^Д^)ギャハ!↑みなさん、この人のレスどう思いますか♪なんてありきたりなんでしょうね♪
誰もが皆、一瞬つけてみたくなる発想のレスです♪
しかし、賢明な人はその自らの短絡的思考を野放しにする事を嫌がり、
こういうレスは控えます♪しかし、この人はしてしまったのです(^^;
「誰もが思い付くような事」を堂々と♪
この人にとってこのレスは何なのでしょうか♪
このレスをしている間にも時間は刻々と 過ぎ去っているのです♪
正にこの人のした事は「無意味」「無駄」でしかありません♪ああ・・・何ていう事でしょう(^^;ワラ
図星で泣いちゃうかも(^^;ワラ
>>368 今のところ、Singletonで確実に一度しか実行されないことを保証するのに
volatileでは解決にならない、ってことは結論出てるけど、決定的な一貫性を
必要としない、falseがtrueに変化するだけのフラグに使用することに関しては
まだ話題に上がってないと思うんだけど。
>>382 threadの書き方もしらねーじゃねーの( ´,_ゝ`)
VBかDelphiでスレッドかいてるのがバレバレ
a= 1 と x = b の間には依存関係はないから、OoOをサポートした大抵のCPUで
実行される順序は保証されないんじゃないかなー。
Pen4のOoOの仕様についての質問なら多少スレ違いじゃないか?
>>384 漏れ手元に環境ないからわからないんだけど、IA64でスレッド/CPUの対応を
固定にして実行させると、単に参照している側は永遠にキャッシュから幸せに
falseを読み出し続けるような気がする。
もちろんSleep(100)の間に、他スレッド・プロセスの実行によってキャッシュが
無効になる可能性は十分あるけど。
ひとりごとなら駅の裏でアリを相手に言えばいい
>>386 こういう負け惜しみ言うやつって
仕事じゃ使えないんだよな
話の腰を折って申し訳が無い。面白そうなのでいろいろ試してみたいのですが、
キャッシュの影響でスレッド間で同期が取れない状況というのは
Pentium4のHTでも起きるのでしょうか?物理的には1CPUだから無理なのでしょうか?
>>387 Coherent Cacheだから無問題。
一貫性が崩れるのは他のCPUに伝わるまでのわずかな時間だけ。
さすがにそうじゃないアーキテクチャの場合(あるのか知らないけど)は
重要な前提が崩れるわけで、他でも悲惨なことになるんだろうね。
>もちろんSleep(100)の間に、他スレッド・プロセスの実行によってキャッシュが
>無効になる可能性は十分あるけど。
これは十分というより確実にあるでしょ。CPUがスレッド数より多く、さらに
その場合はOS側でコンテキストスイッチを行わないような実装になって
いればありえるかもしれないけど、そんなの現実的じゃないし。
で、SingletonのDCLの場合は、ひらたく言えば、ある変数の読み取りと
書き込み(+比較)を、必ずしも同期なしでAtomicに行うことができるか?
という命題と捉えていいと思う。
今のフラグの話題に戻ると、DCL問題ほど制約は厳しくなくて、読み取る
タイミングは必ずしも正確である必要はなく、書き込み側では読み取りは
一切無く、1ビット(Cだと1ビットでも立ってればtrue扱い)の書き込みのみ。
Reorderされようが、最終的に1ビット立ってりゃいいだけってこと。
volatileがなければ、ループ前に最適化でレジスタにキャッシュされて、
そのまま永遠に回し続けられる可能性も否定できなくなる。
これでも*絶*対*に*同期しなきゃいけないんだろうか?
同期しなくてもいい場合を一生懸命探しているスレはここですか?
synchronization eliminationは非常にメジャーな研究テーマです。
もともと、同期しなくてもいい場合なんて探すまでもないでしょう。
>>392 はそこいらじゅう同期オブジェクトだらけのプログラムでも作ってるのでしょうか?
メインスレッドでやるとウィンドウが白くなって、(応答なし)って
出るような場面だけマルチスレッドにすればいいんだよな?
基本的にはスレッドにできる死したほうがいいのはすべてスレッドにしてます明日が何か?
>>396 同期できてないんじゃないか?なんか出力がおかしいぞ。
ハァ?volatile宣言しているから*問題ない*はずですが?
>>397 おもしろい。というのはさておき、
>>391 Windowsしかも1CPUの環境でしか、マルチスレッドプログラミングしたことないヘタレだけど、
>>338 的なことはフツーにやってんだけど、やっちゃいけないことってされてたの?
危ない橋を渡ってたんだろうか?
オレは単純だから
>>338 みたいなコードが無限ループみたいになるんだったら、volatileの存在意義なんてないって思ってたんだけど...
間違い?(とされてたのか?)
だれかホントのことを教えてくれ。むちゃくちゃ気になる。
>>386 「OoOだから保証されない」じゃちょっと不十分かな。
「どういうメモリ操作が」OoOで実行されるかってことまで突っ込んで欲しかった。
>369のコードで「threadA()とthreadB()がともに0を返すことが起こり得ない」ためには
どういうmemory orderingが要求されるか、ってのは重要。
あるアーキテクチャでは、Double-Checked Lockingは正しく動作するが
Dekker's Algorithmは動かない、それは何故か。なんて話にも繋がる。
少なくともこの程度は意識できていないと、規格厨には対抗できんぞ。
すまんせん、OoOってなんでしょうか。
ググってみたが関係しそうなのが見つからなかったっす。
OpenOffice.org
「OoOだから保証されない」正解者全員プレゼント
クイズに当たると最高100万円等が正解者全員に当たる!
1問コース 小物、アクセサリー 2問 鞄、雑貨、
3問 指輪、アウトドア 5問 商品券、家電、食品
6問、ゲームボーイアドバンス、折りたたみ自転車等
10問 PS2、2万円、サイバーショット、GQ、ブランド物等
15問 10万円、VAIO U、ビデオカメラ
20問 30万円、VAIO QR、VAIO W 25問 100万円
>>405 賞品にママの手づくりジャムが入ってないよ〜
>>403 雑音はおいといて、Out of Orderの略。
とにかく、volatileって書いておけば、マルチスレッドでも大丈夫、ということ。
釣られないぞ。
スレ全体の流れとしては、
当初は、
>>338のようなコードはダメの典型(必ず同期を取る必要がある)とされてきたけど、
今は、
>>339,
>>340のいうような緩やかな同期というか成り行き任せの同期が
許される状況では
>>338 のようなコードも選択肢のうちに入れてよいのでは?
ってことになってるってことでOK?
そして、C/C++ Users Journalの記事に反論できる猛者の出現を待っていると...
>>402 write → readがout of order実行されるとダメってことですかね。
例えばIA32だとこういう操作がout of order実行される、とかってどこかに書いてあるの?
>>410 > 今は、
>>339,
>>340のいうような緩やかな同期というか成り行き任せの同期が
> 許される状況では
>>338 のようなコードも選択肢のうちに入れてよいのでは?
同期というより、なおかつ変更があった直後に気付くという保証が不要で、
そのうち気がつけばいいやという程度なら、ですね。
×変更があった直後に気付く
○変更があった後の最初のチェックで気付く
>>412,
>>413 あっそうか...
この場合は「同期」という言葉は不適切だね。
修正ありがとう。
あ... っていうより、もともと同期を必要としていない状況なのにもかかわらず、
「何で同期しないんだ!」ってことになってたからおかしくなってたんだ...
補足。
もちろん、同期を必要としない状況下で同期しても害はないね。
ここはお前の日記帳じゃあねえんだ
チラシの裏にでも書いてろ
>>417 いまここに必要とされている人は、C/C++ Users Journalの記事に対して反論できるほどの識者であり、
もはや,あなたのようにノイズを撒き散らすだけがとりえの人間の居場所はありません。
より正確には、あなたの存在自体がノイズです。
ノイズはノイズらしく消えてください。
っていうか、volatile最強じゃね?
と無限ループで夜は更けていく
>>420 もう更けるのかよ!
北極圏にお住まいなのかよ!
volatileで
>>338のようなコードの無限ループ化は防げますが、
2ちゃんねるの議論の無限ループ化は防げません。
ってことでOK?
volatile厨厨完全に沈黙wwwwwwww
VHDLならいつもぱられリズム
volatileカワイイヨvolatile
volatileを恐れなく使う兵達のスレ
でも立てるか
このスレの住人のSMPなマシンの保有率を調べてみたい
428 :
デフォルトの名無しさん:05/02/12 07:09:05
なんか良く判らないけどDUAL CPU用のトリップ検索ソフト作って。
仕事じゃ4 way, 8 way, さらには16 wayなんてマシンも扱っていますが、何か?
プ
情報処理試験(エンベデッド)の問題について教えてください。
セマフォの記述として、適切なものはどれか。
ア P操作待ちのタスクはキューで管理される。
イ V操作待ちのタスクはキューで管理される。
ウ デッドロックの心配がない排他制御の手段である。
エ 排他制御の目的以外には使用できない。
(平成10年度 ES 午後 問32)
正解がアかイかでちょっとだけ揉めています。どちらが正しいと思いますか?
>>431 調べりゃ分かるが、確保するのがPで返却がV
queue使うのはP操作待ちの方だな
オランダ語が由来だっけ?
それにしてもあまり出来のいい問題じゃないと思うなあ。
>>432 セマフォの返却を待つタスクが並ぶキューというのはないのですか?
それがP操作の九だって・・・・・(´・ω・`)
そのキューではV操作を待っているんですよね?
||ヽn/|, --- 、
|i/^r ヘ、
く, '/彡 (ノノ))))i| 待ちタスク管理したいな
|N ミ| | ┃ ┃ | |
| lヽ| | ''' ヮ''ノi | ______
| | ⊂}|i † i|{つロ / ロ ロ ロ /
Vy と.l_/_|_j_〉 / ロ ロ ロ /
 ̄ ̄ ̄ ̄ ̄ ̄
ダレダ、オマエハダr(ry
ほんとだ。
見たはずなのに気づいてなかった。
とりあえず読んでみます。
>>432 お前は知識は申し分ないが、日本語の能力に問題がある。
>>336にあるようなDCLP実装ですけど、次のような方法はどうでしょう?
Singleton* Singleton::instance() {
if (pInstance == 0) {
Lock lock1;
if (pInstance == 0) {
Singletom* volatile temp;
{
Lock lock2;
temp = new Singleton;
}
pInstance = temp;
}
}
return pInstance;
}
上のコードは、Lockの確保/解放をまたいでコードが移動しないことを前提としています。
Lockの用途を考えるとLockの外側にコードが移動することはないと思いますが、
Lockの内側にコードが移動することがあるのかどうかが不明です。
>>442 散々既出。(・∀・)カエレ!!
これだからvolatile厨は・・・。
>>442 > 上のコードは、Lockの確保/解放をまたいでコードが移動しないことを前提としています。
> Lockの用途を考えるとLockの外側にコードが移動することはないと思いますが、
それって言えるの? 少なくともセマンティクス上はロックだなんてコンパイラは
関知しないから普通にありえるんじゃないの?
> Lockの内側にコードが移動することがあるのかどうかが不明です。
lockだと認識してもありえるんじゃないの?
Javaのsynchronizedもこれはありえたと思う。
>>444 > それって言えるの? 少なくともセマンティクス上はロックだなんてコンパイラは
> 関知しないから普通にありえるんじゃないの?
確かにそうなんですが、これが保証されてないとロックは使い物になりません。
コンパイラを限定するか、普通のコンパイラであれば問題ないように
実装されているのだと想像しますが、ライブラリのスペックとして
どのように決まっているのかを知りたかったのです。
> Javaのsynchronizedもこれはありえたと思う。
おっしゃるとおり、Javaではありです。
C/C++(あるいはC上でのライブラリ)ではどうなのか、ということです。
>>446 読みました。
>>442のコードは2つほど問題があるようです。
1つ目。
new SingletonがpInstance = tempよりも前に実行される必要があるが、
これは必ずしも保証されません。
ロックが完全同期をとるメモリバリアの場合や、
メモリモデルがTSOのようにwrite→writeの順序が逆転しなければ
問題なさそうです。
しかし、acquire/release型のメモリバリア(release consistencyというのかな?)の場合
release後の読み書きは同期されないため、write順が逆転すると意図通りになりません。
2つ目。
Singleton::instance()で取得したオブジェクトを読み書きするときの例として以下のコードを考えます。
SIngleton* p = Singleton::instance();
p->x;
もしメモリモデルが(Pentium4のように)read→read順序が保証されないものだったとすると、
p->xがpの代入より前に行われる可能性があります。
(ただp->xはpに依存しますので、実際には順序が入れ替わることはないような気もします)
特定の環境では動きそうですが、確かにポータブルな書き方はなさそうですね。
どうもありがとうございました。
> p->xがpの代入より前に行われる可能性があります。
そりゃいくらなんでも...
ヴォラヴォラヴォラヴォラァァー
450 :
デフォルトの名無しさん:05/02/19 10:17:34
volage
Win32でブロックしているスレッドのブロックを解除する方法ってないのかな?
具体的にはReadFileでブロックしているのを特定の時に解除したいんだけど、
TerminateThreadでスレッドをヌッ殺すのはあんまり良くない見たいだし。
オーバーラップi/oにして、WaitForMultipleObjectsあたりで、ほかのイベントも
受けられるようにしとくしかないのかな。
>>451 CloseHandle()したら強制エラーリターンしないだろうか。
・・・すまん、試してないので真偽は不明。
>>452 それはやってみたけど駄目でした。CloseHandleした他のスレッドまでブロックして
戻らなくなってしまいましたよ。
ソケットのハンドルならcloseするとrecvがエラーリターンするからもしやと思って
試してみたんだけどね。
>>453 やっぱ重複i/oですか。UNIX(solaris)で使ってたコードを移植してるんだけど、
UNIXだとシグナルでブロックを中断させてるから似たようなことできないかなぁ
と思ったもんで。重複i/oにしときます。
でもだとすると、同期i/oつかったアプリってブロックを解除する手立てがないとすると、
ウィンドウの×ボタン押されたときってどうやって終了すればいいんだろ?
別スレッドからTerminateThreadとかExitProcessとか乱暴な方法しかないような
気がするけど。それともコンソールアプリでしか使うなって事なのかな。
>>454 ×ボタンだとWM_CLOSEが飛んで来て普通は終わる。無視するのも自由。
無視して動き続けるとタスクマネージャからユーザーに止められる。
シャットダウン中だと暫く待って強制終了。
使われるのはおそらくTerminateProcessかその類似品。
TerminateThreadして動き続けるのはゴミ残るから(・A ・)イクナイ!けど、
ExitProcessはプロセス間で共有するリソースを使ってるような場合を
除いて問題なし。大半のリソースはプロセスと共に解放される。
Windowsのsignalってどういう設計なんでしょうか。
スレッドではなく、純粋な割り込みと考えてよいのかな?
いんや
Windows に signal なんて無かったと思うけど・・・
CRT/src/WINSIG.c 嫁。
>>455 WM_CLOSEが飛んで来たとき、何とかしてサブスレッドのブロックを解除後、
サブスレッドを終了。
メインスレッドでWaitFor何がしObjectでサブスレッドが終了するまで待機後、
サブスレッドのハンドルをクローズ。その他諸々のハンドルを閉じてプロセス
終了へ。と言う風に思ってたんだけど
終了時ならそんなにムキになって後始末しなくていいんだ。
俺様専用チラシの裏
少し前に「Windowsではmutexの静的な初期化が出来ない」という
話があったような気がするが
実際に必要になりそうなケースに遭遇したので、解決法の案。
(double-checked lockingなのは趣味だから気にするな)
static data_t *data;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
if (!data)
data = get_initial_data();
pthread_mutex_unlock(&mutex);
pthreadでは↑のように行う処理を、Windowsでやりたい。
CRITICAL_SECTION *csection;
if (!csection) {
CRITICAL_SECTION *p = new CRITICAL_SECTION;
InitializeCriticalSection(p);
InterlockedCompareExchangePointer(&csection, p, NULL);
if (csection != p) {
// 解放部は場合によっては不要だと思われる
DeleteCriticalSection(p);
delete p;
}
}
EnterCriticalSection(csection);
以下略
面倒ではあるが、こんな感じで正常に動くと思うのだが、どうだろうか。
環境:
WinXP Pro
VC++ 6.0
マルチスレッドのサーバプログラムを作りたいと思っているのですが、
参考になるようなHP又はアドバイス等ありましたらご教授願います。
サーバの処理内容は、SQLDBに接続して処理結果を
クライアントに返すというものです。
>>462 自前でマルチスレッドサーバプロセスを作るのは面倒なので、COMコ
ンポーネントを作ってCOM+に登録するというのはどうでしょうか。
スレッドやトランザクションの管理をお任せに出来るのが楽だと思
います。COMコンポーネントの作成に抵抗がなければですが……
>>463 曖昧な質問に答えて頂いて有難うございます。
VC++はあまり弄った事がないので、
まずはCOM+について調べてみたいと思います。
>>456 構造化例外の成れの果て
だったと思ったけど。
>>465 だな。準拠のためのやっつけ仕事。
な〜んの役にも立たんぞ。
マルチスレッドって何?(main()もスレッドらしいけど)
どうやって作るのか教えて下さい。
そもそもその定義とは何ですか?
環境は、VC++.net2003又は、bcc5.5です。
beginthreadex関数のサンプルを見ろ。
糞初心者が。
470 :
デフォルトの名無しさん:05/03/15 05:37:07
pthreadとboostどちらが可搬性がありますか?
boostのthreadは、C++コンパイラが古い環境だと動かないだろ
自分でboostやg++をmakeする気持があればどっちも同じ。
実際古いコンパイラが問題になることなんて無いと思うけどね。
新しくすればいい。
>>470 boostはWindowsでも使える。
pthreadはWindows上では動かない。
そういう意味ではboostの方がポータブルだな。
・・・まあCygwin使えばpthreadも動くわけだが。
>>474 確かにNTにPOSIXサブシステムがあったのはそれが理由だが
SFUは違うというか普通にMacOSX対策じゃない?
>>475 つかえねーPOSIXサブシステムは捨てたから、
POSIX互換が必要ならSFU使えって事でないの?
>>476 導入用件をクリアさえすればいいだけで使えるようにする必要は無いんだから
わざわざ買収までしてSFUに切り替える理由がそれだけでは弱い
使えないと要件クリアしません。
Citrix ターミナルサーバ、Interix SFUは、いい決断だったと思います。
@/A-----------------------------------------
環境
WinXP Pro
VC++ 6.0
VC++でマルチスレッドを用いた複数端末通信プログラムを作っています。
端末との通信はできたのですが、プログラムが終了するときにメモリリークが発生してしまいます。
プログラム構成は以下の通りです。
MainApp : CWinApp (アプリケーション)
MainSock : CAsyncSocket (アプリケーションメインソケット)
SubThread : CWinThread (各端末毎の接続を担当するスレッド)
SubSock : CSocket (端末とのデータ送受信用ソケット)
MainApp::InitInstance(){
g_Sock = new MainSock(); // メインソケット生成
g_Sock->Listen(); // 接続要求待ち
}
MainSock::OnAccept(){
SubThread* pThread = (SubThread*)AfxBeginThread()
スレッドにソケットを引き渡す
pThread->ResumeThread();
}
SubThread::InitInstance(){
m_SubSock.Attach( 渡されたソケット );
}
void SubSock::OnReceive(){
受信データの読み込み
}
A/A-----------------------------------------
デバッグウィンドウのメッセージは以下の通りです。
Detected memory leaks!
Dumping objects ->
C:\Server\SubThread.cpp(17) :
{100} client block at 0x005F2F60, subtype 0, 140 bytes long.
a SubThread object at $005F2F60, 140 bytes long
Object dump complete.
SubThread.cpp(17)には、
IMPLEMENT_DYNCREATE(SubThread, CWinThread)
が記述してあります。
端末との接続用に生成したスレッドが終了していない事が原因と考えています。
スレッド内から AfxEndThread を呼べば終了できる事は確認していますが、
スレッドではSubSockオブジェクトを初期化しているだけで
Run()内でループ処理しているわけではないので、外部からフラグ等で終了させる事はできません。
外部から終了するにはどうすればいいのでしょうか?
そういうスレッドの使い方はしない。
ええっそうなんですか・・・
じゃあ、単純にソケットを複数個用意して、処理を割り当てればいいんですかね・・・?
何か参考になるHPとかあったら教えて頂けませんか?
MFC ソケットでぐぐると一杯出てくるよ。
お好きなのをどうぞ。
マルチスレッドにするのならヒントとしては、
接続のためだけにワーカースレッドを用意して、
通信はメインスレッドに任せるっていう考え方よりも、
メインスレッド側で接続管理をして、
それぞれの通信管理をスレッドに任せる方が、
スマートだと思うけど。
一応、メインスレッドで接続管理、サブスレッドでデータ通信になってます。
@メインスレッドでメインソケットをListenで待機
AメインソケットのOnAcceptでサブスレッドを生成、サブスレッドのメンバ変数にソケットを渡す
Bサブスレッドのソケットでデータ送受信
Cサブスレッドのソケットを閉じる
というところまではできたのですが、Aで生成したサブスレッドが終了できない、という状況です。
>MFC ソケットでぐぐると一杯出てくるよ。
散々ぐぐって色々見てみたんですが、ソースの一部しか載ってなかったり
プロジェクトの性質から使えなかったり、という感じだったので
足りない部分を自分で作ってみたらこんな感じになってしまいました。
それは、4の後にAfxEndThreadなりでスレッドから抜けずに、
スレッドは生かしつづけたままって事?
通常はその流れなら、
@メインスレッドでメインソケットをListenで待機
AメインソケットのOnAcceptでサブスレッドを生成、サブスレッドのメンバ変数にソケットを渡す
Bサブスレッドのソケットでデータ送受信
Cサブスレッドのソケットを閉じる
Dサブスレッドから抜ける(スレッドの終了)
と言う様になると思うんだけど。
途中でスレッドを停止させるケースに対応したいっていうなら、
イベントカーネルオブジェクトなりで、メインスレッド<->サブスレッド間の
通知機構を実装しなきゃだと思う。
スレッドを生かしつづけてソケットだけを生成->割り当てとするなら、
スレッドプールの実装も考えた方がいい。
アプリケーションの終了時リークするのは、スレッドが停止していない状態で、
プロセスを終了しているからでは?
それならば、スレッドの終了をきちんと待ってからアプリは終了するべき。
スレッドの緊急停止は最終手段。
>イベントカーネルオブジェクトなりで、メインスレッド<->サブスレッド間の
>通知機構を実装しなきゃだと思う。
VC++あまり弄った事がなくてソケットの部分だけ調べまくってやってたので、
存在を忘れていました。
今回はとりあえず動かなければどうしようもないので、
Run()の中ですぐSubSock.Receive()を呼んでデータを受信し、
ループ処理せずにAfxEndThread(0,true);で終了する、という方法でやる事にしました。
他にも色々いい方法があるようなので、今度調べてみたいと思います。
どうも有難うございました。
Windowsのマルチスレッドプログラミングを本格的にやりたいのなら、
AdvancedWindows第4版は買っておいたほうがいいよ。
>>487 AfxEndThread()で終了すると、そのスレッド内で実体化したクラスのデストラクタが呼ばれない。
なので、単にreturnする方がいい。
有難うございます。読んでみます&試してみます。
491 :
デフォルトの名無しさん:05/03/18 21:46:31
>488
どんなことが書いてある(その本でしか読めない)の?
493 :
デフォルトの名無しさん:05/03/19 00:59:08
なかなかよさそうですね
volatile
asm volatile ( "breakc 0x0" );
Linuxのシステムで、プロセスをまたいだファイルのアクセスをします。
オススメの排他制御は何ですか?
対象のシステムは、突然電源が落とされる可能性があるものとします。
それもそうでした。(スレ違い)
ごめんなさい。
>>492 おお、懐かしいな。俺が買った頃はまだ「Advanced Windows NT」
だったけど、Win32スレッドの使い方は大部分それで理解したよ。
最近JavaばっかでWin32方面は色々知らん事も多くなってきたから
また買ってみよ。あんがと。
500 ∈(・◎・)∋
Windowsでのスレッド同期でクリティカルセクションを使用するのですが
EnterCriticalSectionでSTATUS_NO_MEMORYの例外が発生する可能性があるそうですが、
皆さんどのように対策していますか?
InitializeCriticalSectionではなくInitializeCriticalSectionAndSpinCountを使えば回避できるようですが
Windows95等では対応していないようなので構造化例外処理を使用してどうにかしたいのですが
スマートな方法が思いつきません(´・ω・`)
>>501 説明文の構成の仕方が変なのは気付いてますか?
「〜ですが、」ばかりで、丁寧語を使っていたとしても、
これではまるで馬鹿な子を見ている様です。丁寧語も中途半端です。
もっと本を読んだ方が良いでしょう。
私が書き直すとしたら、以下のようにするでしょう。
--------------------------------------------------------------
Windowsでのスレッド同期でクリティカルセクションを使用しています。
EnterCriticalSectionにてSTATUS_NO_MEMORY例外が発生する
可能性があるようですが、
皆さんはどのように対策しておられますか?
1つの対策としてInitializeCriticalSectionの代わりに、
InitializeCriticalSectionAndSpinCountを使う方法がありますが、
Windows95等では未対応のため、構造化例外処理からどうにかしたいのです。
スマートな方法が思いつきません。(`・ω・´)
補足ですが、大事なのは最後の眉毛の向きです。
これを読み違えないで下さいね。
それ以外はあまり気にする必要はないでしょう。
Yes,teacher. (´・ω・`)
では次の方、質問どうぞ。
Windowsでのスレッド同期でクリティカルセクションを使用するのですが
EnterCriticalSectionでSTATUS_NO_MEMORYの例外が発生する可能性があるそうですが、
皆さんどのように対策していますか?
InitializeCriticalSectionではなくInitializeCriticalSectionAndSpinCountを使えば回避できるようですが
Windows95等では対応していないようなので構造化例外処理を使用してどうにかしたいのですが
スマートな方法が思いつきません(´・ω・`)
Win95を捨てる。
MSDNによるとInitializeCriticalSectionAndSpinCountは
Win98以降で使えるみたいだから、捨てるのはWin95だけでいいみたい。
どうせもはやMSのサポート終了した製品だし。
Windows以外のOS使え馬鹿
何気に興味深い記事だな
513 :
釣り:2005/03/29(火) 21:53:11
>510
なるほど、C#ではvolatileでいいんですね
.| | | | | | | | | | || | |
.| | | レ | | | | | J || | |
∩___∩ | | | J | | | し || | |
| ノ\ ,_ ヽ .| レ | | レ| || J |
/ ●゛ ● | .J し | | || J
| ∪ ( _●_) ミ .| し J|
彡、 |∪| | .J レ
/ ∩ノ ⊃ ヽ
( \ / _ノ | |
\ " / | |
\ / ̄ ̄ ̄ /
 ̄ ̄ ̄ ̄
volatileとマルチスレッドは全く一切絶対ひとかけらも関係がない
クリティカルセクションというのは
Enter〜Leaveの間はプロセス内のそのスレッド以外は動かないと
言う考えであってますか?
例えば2つのスレッドで同じ関数を呼ぶ場合、その関数の頭でEnterして
最後でLeaveしたとするとその関数自体複数のスレッドで同時に呼ばれる事が
無くなると言う事でしょうか?
考え方は基本的にあってる。
けど関数は自体は同時コール出来る
関数の中に入った時点で片方のスレッドがロックされる。
>>519 回答ありがとうございます。
今そういった感じのアプリケーションを作ってるのですが
どうもその辺りに自信がなかったもので・・・。
あるスレッドがクリティカルセッションオブジェクトにEnterしている間、
同じクリティカルセッションオブジェクトに対してEnterするとブロック(一時停止)される。というだけ。
>>521 その表現では曖昧じゃね?
他のスレッドは少なくともEnterできないと思うが
同じスレッドが複数回Enterできるかどうかはモノによるような。
同じスレッドの複数回Enterでブロックするのならば、即デッドロックなわけだが。
もし「ブロックする」という実装ならば、その旨(複数回Enterするなと)明記されているのが普通と思う。
むしろ、複数回Enterした後、1回のLeaveで解除されるかが
実装依存な部分な気がする。
enter/leaveって何の話なんだ?
>>523 MSDNのLeveCriticalSection()の解説にこう書いてあるよ。
>クリティカルセクションの所有権を解放するには、各スレッドはクリティカルセクションに入るたびに、
>LeaveCriticalSection 関数を 1 回呼び出さなければなりません。
>>524 CriticalSection=Windows固有のプロセス内限定のリカーシブなmutexみたいなもの。
EnterCriticalSection()でロックされて、LeaveCriticalSection()でアンロックされる。
たぶん....。
クリチカルセクション内ではプロセス内のスレッドの切り替えが起こらないというだけだろ。
何を難しく考えているんだか
さすがにそれは違うだろう。。。
>>528 「クリチカルセクション」ってのが EnterCriticalSectionからLeaveCriticalSection間の
ことを指してるんなら、スレッドの切り替えは普通に行われるよ。
Windows 以外の環境の「クリチカルセクション」ってのについては知らないけど。
ぷ
スレッドの切り替えはおきる。
ただし、同一 CriticalSection 間にはひとつのスレッドしか入れない。
スレッド A
EnterCriticalSection(&cs)
printf("A");
printf("a");
LeaveCriticalSection(&cs)
printf("1");
と
スレッド B
EnterCriticalSection(&cs)
printf("B");
printf("b");
LeaveCriticalSection(&cs)
printf("2");
を動かしてみればいい。
"Aa" の間に "Bb" は絶対に入らないが A2a はあるハズ。
532 :
デフォルトの名無しさん:2005/04/18(月) 23:15:23
>526
ヒロシです
ワークパイルとワーカースレッドの違いがわからんとです
おな ぬ
>>532 組み込み用に書かれた OS (というかリアルタイムモニタというか) やプログラムなら、
クリティカルセクションをそんな風に実装することもあるよ。
単に割り込み禁止にしたりしてさ。
536 :
デフォルトの名無しさん:2005/04/19(火) 12:23:55
助けてください!
メインスレッド無限ループ中にKERNEL32でエラーが出てしまいました!
スレッドも最近学んだ程度で、カーネルだって知らない!
助けてください!
無理
538 :
デフォルトの名無しさん:2005/04/19(火) 13:04:22
( ´゚д゚`)そんなー
>>535 クリティカルセクションでスレッドそのものを制御する事も出来るの?
NetBSDに「RAS」という仕組みがあって、ある区間においてコンテキス
トスイッチが起きないようにできます。シングルプロセッサのときは、
RASを使ってpthread_mutex_lock/unlockが実現されています。
それだけではよくわからんのでRASとはどのような仕組みか説明してたもれ。
ググったら Restartable Atomic Sequences だということだけわかった。
コンテキストスイッチを停止する実装では
enter中に数分間の長い処理を行っただけで
他スレッドの処理が止まってしまい困るのでは?
>>543 そういうOSの場合、困らないプログラムを動かすから何の問題も無い。
処理が短いとか別スレッドが動かなくてもいいとか。
>>543 数分も何らかの排他処理を行いたいなら、
mutexやセマフォを実装すれば良いわけで。
んでそのセマフォなりmutexなりの操作する部分だけを
クリティカルセクションで保護する。
一般的な話として、
保護すべき領域をクリティカルセクションと呼ぶのであって、
保護するための仕組みのことではないよね...
>>543 ユーザプロセスが異常な振舞いをしたから他のプロセスの実行に支障が出るってのは
まずいだろ。
enterしたままビジーループに入ってしまったらどうすんの?
>>547 組み込み系だと普通はWDTで電源落ちにします。
タイマー割り込みで点滅させてるLEDがとまるから目で見てわかるんだよ(w
>>543 >他スレッドの処理が止まってしまい困るのでは?
>>547 >他のプロセスの実行に支障が出るってのはまずいだろ。
話がずれてますな。
そう?
>>543はハードリアルタイムを保証するかどうかどうかで、
>>547は協調的マルチタスクを必要とするかどうかじゃない?
いくらなんでもユーザプロセスがおいたして機能不全に陥いるのはまずいべ。
少なくともUNIXでは普通は予期しないだろう。
組み込みで少数のプログラマチームに全ての開発が
任されているならありかなとは思う。
NetBSDなんかが出てきたので混乱されている方もいそうですが、RAS は
>ある区間においてコンテキストスイッチが起きないようにできます。
というような乱暴なものではないと思うんだけど・・・
組み込み用OSでは、まずい設計のプログラムを書けば
まずい結果が得られるのはごく普通。
普通のOSでもデバイスドライバ等では同様。
そもそもシステムプロセスとユーザプロセスの区別があるとも限らんし。
ms-dos + αというイメージだな。
556 :
デフォルトの名無しさん:2005/04/19(火) 20:16:58
マルチスレッドじゃなくてマルチプロセスなんですけど・・
共有メモリに対するアクセスにセマフォを使って
排他制御をかけようとしています。できれば排他ではなくて
reader/writer ロックを実装したいのですが、普通こういうのは
どのように実装するんでしょうか? なんらかのライブラリ?は
なさそうですし・・。ちなみに Linux の C です。
スレ違い、勘違い発言でしたらすみません。。
スレ違いだし、そういう概念的な話は本読んだ方が早い
>>556 UNIXプログラミングスレ言って、
System V IPCのセマフォの使い方聞け。
(man semop)
559 :
556:2005/04/20(水) 00:03:24
>>557 >>558 コメントありがとうございます。
「最前線UNIXのカーネル」という書籍があったので
自分なりに調べましたが、reader/writerの実装は
結構ややこしそう(めんどくさそう)でした。
現状はセマフォで実装しており常に排他になってしまってますが
まあなんとなくこれでしばらくは我慢しようという気持ちに
なってきたところです。
ともあれ、コメントありがとうございました。
560 :
558:2005/04/20(水) 00:51:15
semaphoreあったら、簡単だろ?
reader/writer lockは。一つカウンタ管理するだけだぞ。
ただスレ違いだから、必要だったらあっちで聞いてね。
ps じゃダメなのかな?
ああ、Linuxだと 一個増えて表示されるからややこしいかな?
Solarisならいいんだけど
psってプロセス表示のコマンドの事言ってるんだろうか
だとしたら無茶言うな
563 :
デフォルトの名無しさん:2005/05/15(日) 13:30:23
スレッドの生成コストってどのくらいなのでしょう?
>>564 結構高いんですね。
頻繁に作成消滅を繰り返すよりも、使用しないときはmutexで停止させて眠らせておいた方が良さそうですね。
スレッド生成のベンチマークがどっかにあったような
だいたい1msで作れてた気がするな
条件がわからんが単純にCPUが1GHzとすると、1Mクロックかかるのか。
かかり杉だな
死ねクズって感じ
どのOSのことか書いてないけど
Windowsのbeginthreadexの場合はまずCランタイムの初期化とかもあるし、
内部的にVirtualAllocでメモリマップを割り当てたりCriticalSection
とかで排他したりしてるわけだから、
実際計ったことないけど1msで作れれば良いほうだと思うよ。
これに比べるとUNIXのforkなんか目も当てられない。
ただ、forkに比べてスレッドに割り当てられるアドレス空間は、
プロセスが割り当てるメモリマップに依存し有限だから、
forkのようにいくらでも作れるというわけじゃない。
Windowsのスレッドはデフォルトで1MBのスタックを個別にマップするわけで、
プロセスのメモリ空間が32bitの範囲のOSなら、約2000個のスレッドを
作れれば良い方だと思う。
スタックサイズを調節したらもっと多くできるだろうけど。
つーか1プロセスの最大スレッド数って定義されてたっけ?
誰か試してみませんか?
LinuxはNPTL+kernel2.6で最強になりましたよ。WINDOZE糞杉。
今時の fork(2) はみんな COW じゃないの
Atom Heart Mother やね
>>571 そりゃ後発で糞だったら目も当てられないw
まあスレッドだけ早くなってもXはもっさりのまんまだし、
UNIXって前途多難だよな。
どうでもいいが
> UNIXって前途多難だよな。
2037年が寿命ならもう半分は過ぎてしまったわけで、もう前途はないわけで
>Xはもっさりのまんまだし
これはもう、OSの所為ではなくてプロトコルが余りに古すぎる所為なのだが。
タランテラみたいなミドルウェア経由の方がよっぽど速くなる罠。
(1)のシグナルを受け取るスレッドが他になかった場合、
(2)で自分のシグナルを受信しちゃいます?
pthread_mutex_lock( &mutex );
pthread_cond_signal( &cond ); // (1)
Value = 1;
do {
pthread_cond_wait( &cond, &mutex ); // (2)
} while ( Value != 0 );
pthread_mutex_unlock( &DataProcMutex );
579 :
デフォルトの名無しさん:2005/05/18(水) 23:30:41
アセンブラ言語で文字列操作の「REP MOVS〜」の繰り返し処理中にスレッド切替は発生するのでしょうか?
>Xはもっさりのまんまだし
単純にDisplayの設定を変えるだけで早くなる場合があるがな
>>579 Intel PDF IA-32より
service pending iterrupts (if any)
だから切り替えは起きません。
×iterrupts
○interrupts
>>581 スレッド切替え発生するだろ。
>service pending iterrupts (if any)
それ割り込みじゃねーのか?
割り禁中にコンテキスト切り替え起こすのは難しそうだな。。。
>>583 コンテキスト切り替えって、何らかの割り込みで起こすんじゃねーの?
スレッド2つ立ち上げて、一つは巨大なメモリブロックをREP MOVSなどで繰り返し
転送する重い処理を、もう一つは単純なループなどを実行し、それぞれのスレッド
に実質的に割り当てられたCPU時間を比較してみてもいいな。
あ、でもタイムスライスより長いREP命令なんてなかなかないかも。
587 :
デフォルトの名無しさん:2005/05/19(木) 01:08:19
UDP使ったチャットプログラムを作りたいんだが、スレッドの使い方がよくわからんとです。。
言語はCです。。教えてエロイ人〜!!
ならば、まずスレッドをつかわずにやってみたまへ。
589 :
デフォルトの名無しさん:2005/05/19(木) 01:31:34
レスありがとう、エロイ人!
とりあえず文字列がサーバ(?)からクライアント(?)に送れるようにはなったとです。
でもチャットってサーバとかクライアントとか関係なく送信も受信もできなきゃダメじゃないですか・・・。
スレッド使えばうまくいくのかなぁとか思ったとですけど、うまくいかんとです。
もっと良い方法があるとですか??
まずプロトコ〜ルを決めたまへ
IA-32 インテル アーキテクチャソフトウェア・デベロッパーズ・
マニュアル中巻より
リピート・ストリング操作は、例外または割り込みによって中断されることがある。
とあるから、rep〜中にもスレッドの切り替えはあるでしょう。
(・∀・)
( ・ ∀ ・ )
( ・ ∀ ・ )
(──────────∀──────────)
( (・∀・) ∀ (・∀・) )
・
599 :
デフォルトの名無しさん:2005/05/24(火) 03:27:33
スレッドに関してお教え下さい.
これまで,スレッドを使用したプログラムではいくつかの動作を
メインループから指示するために
WaitForSingleObjectもしくはWaitForMultipleObjectsを使用し
Signalによって動作を起動させていました.
今回,いくつかのパラメータをスレッドに渡す必要が生じたのです
がどのような方法が簡単で安全でしょうか?
>599 CreateThread。
WaitForMultipleObjectsExにして、
QueueUserAPCで渡す。
602 :
デフォルトの名無しさん:2005/05/24(火) 12:58:44
UNIXでgetrusageを使って使用CPU時間を取得しているのですが、pthreadを使った場合、うまくいきません。
全スレッドの合計値を得たい場合どうすればよいのでしょうか?
/proc の下を直接叩いたらいーんじゃない?
pthreadを使っていないのに-lpthreadをつけてコンパイルしても問題なく走りますが、何か弊害はありますか?
メモリーの無駄
えーと・・・(´・ω・`)
>>604 dlopen等でShared Objectをロードする場合なんかは要るかもね。
そいつが-lpthread必要としてたりすると動かないから。
-lpthreadはいくつかのシステムコールとかを上書きするから、
プロセス開始時に一緒にロードされてないと困ることになるはず。
昔の記憶なんで今は違ってたらスマソ。
OSやスレッドの実装によるだろう。
ここの住人の皆様に聞いてみたいんですが、
java.util.concurrent.ConcurrentHashMapって
(*´д`*)ハァハァできまつか?
ハッシュ、ハッシュ!
pthread_mutex_lockとpthread_spin_lockの違いを教えてください。
似たような感じなんですが、どう使い分けましょうか?
ドキュメントといえば、これでしょね。
http://www.opengroup.org/onlinepubs/009695399/functions/pthread_spin_lock.html The pthread_spin_lock() function shall lock the spin lock referenced by lock.
The calling thread shall acquire the lock
if it is not held by another thread.
Otherwise, the thread shall spin (that is, shall not return from the pthread_spin_lock() call)
until the lock becomes available.
この辺りは、pthread_mutex_lock()と実質的に変わらん予感。
The results are undefined if the calling thread holds
the lock at the time the call is made.
は、PTHREAD_MUTEX_DEFAULTのmutexと変わらんと思う。
で、どこが違うのだろうか...
唯一違いそうなのが、spinというくらいだから
カーネルやらスレッドスケジューラによらずクルクル回って
スピンしているのか?だしかにspinするって書いてあるが。
だからどうなの?
>>615 そこまでわかってるなら、パフォーマンスでも比べてみると良いんじゃないかな?
比べてもいいが
それは、たまたま、そのOSの実装でってことだよね。
一般的にPOSIXの定義として
ドキュメントのどこにもパフォーマンスのことなんか
書いていないんだが...俺が見落としているんだろうか?
スピンロックは待ってる間もCPUを使うけれど、
スレッドをブロックさせたりとかいうめんどい処理がないので、
ごく短い時間しか待たないならむしろ効率が良い。
んじゃないかなあ...
>>617 > ドキュメントのどこにもパフォーマンスのことなんか
> 書いていない
スレッドの仕様にパフォーマンスへの要求を含めちゃうと
いろいろよろしくないっしょ
んー、事故解決。
lock期間が長くなりそうな場合はmutex
短い(数ステップ?)ならspin
てな感じでいいや。
パフォーマンスが目的でspinを用意しているなら
mutexよりspinの方がパフォーマンスがよろしい(たいていは)。
ということだけでもあってもいいと思いますが。
CPUが1つしかないマシンでスピンロックを使う利点てあるかねえ?
何で CPU が一つしかない?
> パフォーマンスが目的でspinを用意しているなら
んなわけねーだろ
カーネル周りで使うね。spinlock
>>626 そりゃ自分以外に頼れるものがない寂しい子だからでしょ。
カーネル(のコア)だと sleep 出来ないからだよ
質問なんですが
pthread_createでスレッドを作るときメンバ関数は
そのままでは入らないみたいなのでぐぐってみたところ
この関数を入れれば良いとのことでした
static void *ThreadEntry(void *ptr){
static_cast<CLASS *>(ptr)->Thread(ptr);
return ptr;
}
しかし、この関数で呼んだメンバ関数Threadはメンバ変数を
使うとSegmentation faultしてしまいます。
なんとかpthread_createでメンバ関数をスレッドとして
立ち上げることはできないでしょうか?
環境はFreeBSD4.11でコンパイラはg++です
よろしくお願いします
pthread_createの呼び出し側コードを晒せ
631 :
629:2005/06/12(日) 12:22:15
>>630 pthread_create(&tid[i], NULL, CLASS::ThreadEntry, (void *)i)
これです。"i"はスレッド番号
最期の引数の型は?
633 :
629:2005/06/12(日) 12:25:30
スマソ intです
その引数の値が ThreadEntry の ptr に入ってくるってのは理解しているのか?
つまるところ
static_cast<CLASS*>((void*)i))->Thread((void*)i);
を実行していることになる。
Cの勉強しなおしたほうがいいんじゃねえの?
635 :
629:2005/06/12(日) 12:36:17
ということは最後のところにインスタンスのポインタを入れればいいってことですよね
・・・自分のオブジェクトってどうやって取得すればいいんでしょうか
適当な関数作って引数として自分のポインタをもらうしかないのかな・・・
うん、やはりマルチスレッド以前に
C/C++の基礎を勉強すべきだ。
マルチスレッドのプログラムを作っているのですが、CPUの数に応じて、実行方法を変えたいのですが
CPUの数を取得する方法がわかりません。LinuxでCPU数を取得する方法を教えてください。
>>637 リナザウしか持ってないから分からんけど、/proc/cpuinfoでも見れば
分かるんじゃないの。わかんなかったらLinux板でも行って聞いて。
ここじゃ板違いだし。
>>635 「this」って予約語知らない奴がマルチスレッドか…こんなんだから…
関係ないが (void*) と static_cast<CLASS*>() が混ざってるのもキモイな。
でも全部static_cast< にされたら読みたくないよね(w
static_cast<CLASS*>((void*)i))->Thread((void*)i);
static_cast<CLASS*>(static_cast<void*>(i))->Thread(static_cast<void*>(i))
>>640 >>642 の様に長くなって読みづらいけど… cast の種類が明示される方がいいという考え
方もあるのだよ。
Cタイプのキャストだと、reinterpret_cast と static_cast の違いが明確でないし。
って、スレ違いスマソ。
1年に1回くらい、
>>629 と同じような質問こない?
言語がわからないようなアホは
スレッドなんてやるなって。
って会社で言ったら、
「そんなの難しいのが悪い」と真顔で反論されたことがある。
それを簡単にするのがおまいの役目
ラッパークラスでもなんでも作りやがれや
スレッドはラップできても言語仕様をラップするのは難しいな
プログラマ資格制への移行が期待される今日この頃
まず最初に党員に(ry
人命に関わるところなら導入済みだろうけど
金に関わるところですらまだ曖昧なままだし
法で縛らんとだめだろうね
>>645 たとえ俺に役目があったとして、
お前の無努力や無能力が正当化されるわけではない。
いくらスレッドをラップしたところでデータレースやデッドロックを意識しないで
プログラムを組むのは難しくないか?
なんでもAPI一発でインスタントにできると思ってるWin厨の出る幕じゃねえってことだぜ。
積分が足し算のように簡単にならないのは積分の馬鹿な仕様のせい。
おまえが馬鹿だからだろ
>>651 なんでもAPI一発でインスタントにできると思ってる上司に
真顔で一発でできるようにしろと言われたことがある。
まあ、技術は弱いけどマネージメントできる人だからいいんだけど。
ここで質問したほうがいいのか?
linux の boost::thread で 400 以上のスレッドを作ろうとすると
リソース不足の例外が発生してそれ以上作れないのだが、
この上限をもっと増やすにはどうしたら良いのだろうか・・・?
「終了しているのにスレッドが残ったまま」
とネットワークプログラミングのスレには書いてあったが、何故ここでも書かない?
thread::join()とかpthread_join()は理解できているの?
>656
残ったままというのはもう解決したから。
しかし、次のステップでは 400 以上平行して走らせたいのだ。
どうやら、スタックのメモリ量が関係しているらしい事までは
掴んだ・・・が、ulimit -s で少なめにしてみても、今度は
システムがスローダウンして・・・なにが起きているのやら・・・
400以上のスレッドって…。
64CPUとか128CPUのマシンをパーティショニングせずに運用するのかな。
カーネルパラメータ
>>659 つーか今度はthread数の上限(ulimit -u)は解決してんじゃん(w
遅いのは仕方ないでしょ。(たぶん)CPUもメモリも喰ってんだから。
結論:犬糞は400スレッドも満足に動かせない糞OS
つーかswap足りないんじゃない?
空きがなくなりそうになると極端に遅くなるから。(スラッシング)
400以上のスレッドが必要な処理ってどんななんだ?
作りがショボい or ハード/OSの選定ミスだとは思うが。
>>665 俺も思った。何か致命的な設計仕様上の欠陥がある気がする。
そんなに必死になって擁護しなくていいからw
犬糞はスレッドが実行されるCPUを限定することができない糞OS
スレッド数は問題ないでしょ。
通常のdefaultは2000超えるからね。
それ以上必要で、リソースが十分なら、ulimit -uで増やせばいいだけだよ。
メモリかスワップが足りないだけじゃない?
別のメモリ大量マシンでも試してみた ・・・
なんか現象変わらず ・・
ulimit とかでイロイロ試すと、さっきまで
落ちていた場所では落ちなくなったものの ・・
なぜか、スレッド 300 作る辺りまではすごく
高速に生成できるのに、さっきまでエラーで
落ちていた回数を少し超えた辺りから、生成
スピードが指数関数的に遅くなり、330 ぐらい
でシステム全体のレスポンスが極端に遅く
なり ・・・ 固まった。 orz.
なんなんだこれは?
どうにも良く判らないな ・・・
カーネルにスレッド数のパラメータなんてあったっけ?
何か致命的な設計仕様上の欠陥がある気がする
スレッドの処理中に動的にメモリ確保とかしてないよね?
Solaris だと lockstat, truss, prstat -L あたりで何となく分かる事もあるけど、
Linux のコマンドでも同じ様なのあるでしょ。
>>670 実装メモリとCPUパワーが足りないんだよ。
Athron 64 x 4 + Memory 32GBくらいにしてみ?
ども。お騒がせしたが、自己解決した。
ulimit でスタック使用量減らしたら生成できるスレッド数の限界は解決した。
沢山生成で遅くなったのは、スレッドの開放が usleep 呼び出しでできるものと
思い込んでいたのが原因だった。Windows では Sleep() で開放してたんで。
sched_yield() をいれてやったら、アッサリ 3000 以上生成できるようになった。
(ulimit でスタック使用量を 10 分の 1 にした時)
>>676 > スレッドの開放が usleep 呼び出しでできるものと思い込んでいた
orz
基本もわかってねぇのかよ・・・
そんなだからWin厨って言われるんだよ・・・。
yieldなんかに頼らないで、条件変数使って初期化終わるまで
待機させて、broadcastして一気に目覚めさせればいいのに。
WindowsだってEvent使って初期化終わるまで待機させた方が
お行儀のいいプログラムになると思うぞ?
タイムスライスの放棄のことかよ。
これだから犬厨は。
犬糞でもsleep(0)でできなかったっけ?
>>676 > スレッドの開放が usleep 呼び出しでできるものと思い込んでいた
< スレッドからのCPU明け渡しが usleep 呼び出しでできるものと思い込んでいた
だろ? orz
俺もBoost.threadでテストしてみた。
WindowsXpだと全体で5000くらいが限度みたいで、VC++でもmingwでもおなじ。
CPUはPentium-M、IA32でのスレッド上限は8192個らしいからそんなもんかもしれんが。
メモリ食いなのでリンカのメモリ設定をいじるうまくいく。
mingw-gcc なら -lW,--heap,1024,--stack,4096とか、
1秒に一回 std::string s を s+="x";するだけのスレッドを約5000個起動、
スレッド生成時は100%負荷がかかる、1秒で100個程度しか作れない。
boost::thread_resource_error例外がバンバンでたあたりで、
システム全体の調子が変になり、動作は重くは無いが、他のプロセスが起動できなくなる。
全スレッド生成後タスクマネージャは平均10%の負荷、50MBくらい使う、チクショウ、
タスクマネージャー自体がややフリーズしはじめたので、これはたぶん正確ではない。
なんにせよスレッドがいちどきに最大たったの5000程度しかうごかないのは残念だ、
しかも、OS全体で5000で、プロセスごとに5000が上限ではない、
つまり1000個のスレッドを同時に動かすプロセスは5個が限度というこった。
WIN64やらEM64Tやらなんかではどのくらいまで平気なのか気になる。かゆうま。
(゚з゚) ♪De Do Do Do, De Da Da Da...
>>684 > CPUはPentium-M、IA32でのスレッド上限は8192個らしいからそんなもんかもしれんが。
(゚Д゚)ハァ?
IA-32自体にそんな制限があるわけないが、WindowsではLDTのエントリ
数が上限だった気がする。
pthread について質問です。
OS は Linux です。
pthread_cleanup_push によってクリーンアップハンドラを登録します。
そのクリーンアップハンドラの中で、さらに pthread_cleanup_push を呼び出すことは許されるのでしょうか。
というのは、確保したリソースをクリーンアップハンドラで解放したいのですが、この解放処理に排他制御が
必要なのです。
排他処理には mutex を使っているのですが、pthread_mutex_lock の前に pthread_cleanup_push を行って
pthread_mutex_unlock を登録しているのです。
いかがなものでしょうか?
実は別スレで質問したのですが、スレ違いを指摘されてこっちに移動してきたのですが、よろしくお願いします。
689 :
688:2005/06/22(水) 20:07:24
age忘れたので age
690 :
デフォルトの名無しさん:2005/06/24(金) 01:10:35
メッセージキューを使用したい。
詳しく教えてはくれまいか。エロイ人。
Xちゃんとお話したいスレッドA君、B君とXちゃんのあいだにスレッドQ太郎を置く
A君がXちゃんにお話したい時はQ太郎にお願いする
Q太郎はA君のお願いを自分のキューに入れる
B君もXちゃんにお話したい時はQ太郎にお願いする
XちゃんはA君やB君やC君がいようと
Q太郎から単純に順番にお願いをとりだすだけで済む
Q太郎はたいがい一人だなぁ
XちゃんがQ太郎を通じて「誰かヒマな奴これやっといて」とスレッド達に適当にお願いする、
というシチュエーションはよくある。
Q太郎はおひるね中です。
あずかったお願いも、犬に追いかけられているうちに
なくしてしまいました。
でもQ太郎は気にしません。元気がとりえです。
NT以降でコンテキスト管理にLDT使っているOSってあるのか?
698 :
デフォルトの名無しさん:2005/06/24(金) 22:16:59
マルチスレッド”プログラミング”の情報はWebにいくらでもあるけど
マルチスレッドのスレッド構成の指針みたいなのはWebに情報ないよね。
と思った。
>>688 なんで、
void my_cleanup_handler(void*) {
:
:
pthread_mutex_lock(...);
排他が必要な解放処理;
pthread_mutex_unlock(...);
}
ではダメなの?
SUSにはとくにできるともできないとも記述されてないように見えるけ
ど、素直に実装したら、クリーンアップ中にpushしてももう手遅れな気
がする。
700 :
688:2005/06/25(土) 00:51:15
>>699 その処理が汎用的な処理だから。
生きてるスレッドから呼ばれることもあるんです。
なんでそういう処理をスレッドに後始末させるかな
702 :
688:2005/06/25(土) 01:07:04
その処理ってのは多重ロックの実装で、ロックカウンタを操作するのに排他が必要で、それに mutex を使ってる。
ロックを獲得する関数を呼んだならば、それを解放する処理も必ず呼ばなくちゃいけない。
だからその解放処理をクリーンアップハンドラに指定するんだけど、その解放処理自身も mutex を使ってるから、
mutex の解放を確実にするため、pthread_mutex_unlock もクリーンアップハンドラにしたい。
処理を単純化して書くと、こんなかんじ。
void my_lock(void *my_resource)
{
pthread_cleanup_push(pthread_mutex_unlock, &mtx);
pthread_mutex_lock(&mtx);
ロック処理
pthread_cleanup_pop(1);
}
void my_unlock(void *my_resource)
{
pthread_cleanup_push(pthread_mutex_unlock, &mtx);
pthread_mutex_lock(&mtx);
アンロック処理
pthread_cleanup_pop(1);
}
で、
pthread_cleanup_push(my_unlock, &my_resource);
my_lock(&my_resource);
なんらかの処理
pthread_cleanup_pop(1);
というわけ。
そんなにおかしなことしてる?
703 :
デフォルトの名無しさん:2005/06/25(土) 10:22:27
sem_wait について質問です。
この説明は正しいですか?
http://www.linux.or.jp/JM/html/glibc-linuxthreads/man3/sem_init.3.html 引っかかる点は、「sem で指定されるセマフォのカウントが非 0 になるまで呼び出しスレッドの実行を停止する。」というところです。
「非0 になるまで」ではなくて、「0 になるまで」の間違いではないでしょうか?
あともう一点。
sem_wait は、取り消しポイントということになっています。
ということは、次のようなコードは間違いになりますよね。
pthread_cleanup_push(sem_post, &sem);
sem_wait(&sem);
処理
pthread_cleanup_pop(1);
では、スレッドがキャンセルされたときにセマフォの解放を確実にしたい場合、どのようにコーディングすればいいのでしょうか?
> 「非0 になるまで」ではなくて、「0 になるまで」の間違いではないでしょうか?
非0であってる。
sem_waitは、セマフォが0より大きければ1減らして通過。
セマフォが0なら1以上になるまで待って、1減らして通過。
705 :
703:2005/06/25(土) 16:19:52
>>704 なるほど。
じゃあカウンタの初期値は 1 とかにしておく、ってことですか。
ありがとうございます。
あとは取り消しポイントであることについての疑問が残るのみです。
どなたかよろしくお願いします。
え?
sem_waitの最中に取り消されたなら、クリーンナップは要らないだろ。
つまり、資源を取得していないうちに、開放するようなコードを書いてはいけない。
sem_wait(&sem);
pthread_cleanup_push(sem_post, &sem);
処理
pthread_cleanup_pop(1);
>>706 問題は、sem_wait が完了した後に取り消されたときなんです。
それに備えてクリーンアップハンドラを登録しようにも、その登録を sem_wait の前でやっても
後でやっても具合の悪いタイミングが存在しますよね?
それとも、sem_wait 〜 sem_post の間には、キャンセルポイントが無いようにしないといけないという
ことなのでしょうか?
>>708 sem_wait の後で登録したら、どう具合が悪いの?
>>707 それだと、sem_wait がキャンセルされて復帰した場合、セマフォの獲得をしていないにもかかわらず
セマフォの解放を行ったりしませんか?
と言ってみたものの、もしや sem_wait が復帰するときというのは、必ずキャンセルされていないことが
保証されているのですね?
キャンセルされたら、sem_wait から復帰することなく、クリーンアップ処理が走る、ってことでしょうか?
意味がわからない。
キャンセルされて復帰したとはどういう事だ?
sem_waitがキャンセルされたなら、事前に登録してあるクリーンナップ
ハンドラが呼ばれて、そのスレッドはそこで終わりじゃないのか。
>>711 はい。理解しました。
自分でも何を勘違いしていたのか疑問です。
713 :
デフォルトの名無しさん:2005/06/27(月) 02:16:21
orz って今の今まで、
○| ̄|_ の小さい版とは知っていたが、
四つんばいとは知らなんだ。
拳を握り、目を細めて ウググググ・・・って悔しがってるのかと思ってた。
714 :
デフォルトの名無しさん:2005/06/27(月) 03:11:43
> 拳を握り、目を細めて ウググググ・・・
が分からん。orz
漏れもわからん・・・
とりあえず漏れの解釈。
顔の線
↓
○| ̄|_
↑ ↑ ↑
拳 目 鼻
伝説の予感・・・
o/z-/b
@@@
@@@@
○| ̄|_  ̄|○
\◎/
| | ̄|_ ○| ̄|_ orz
短足だから見間違えたんだな。
○| ̄|_
なら顔には見えまい。
@@@
@@@@
○| ̄|_  ̄|○
\ー/ ニヤリッ
にしこり
725 :
713:2005/06/27(月) 19:49:48
そうです。
新キャラ誕生の瞬間を目撃!?
727 :
713:2005/06/27(月) 23:54:47
顔の線
↓
○| ̄|_
↑ ↑↑
拳 目 口
これ、口だから。崩さんといて。<@
く、口なのか?
729 :
713:2005/06/28(火) 00:08:58
>>702 クリーンアップしてる間はキャンセル禁止(か遅延)にしとけば?
クリーンナップ中にpthread_setspecific()したら
再度クリーンナップされるのはPOSIXの正しい仕様ですか?
哲学者にレイプされました。アノ人たちにとってアタシは共有リソースだったんです。
三つの穴にとっかえひっかえ入れられて。入れてない哲学者は瞑想にふけて、
順番が来るのを待ってました。
アタシはセマフォなんて信じない。
デッドロックは無かったです。(T T)
入れる物が一つならデッドロックはないわな
○| ̄|_ ̄|○
○| ̄|_ ̄|○ <デッドロックに耐えてよくがんばった!
クラス内の関数をスレッド化することを考えています。
for (int i=0;i<threadnum;i++)
{
if(pthread_create(&tid[i],NULL,(THREADFUNC)threadRoutine,(void*)i) != 0)
{
perror("pthread_create");
}
}
と書くと、3行目のところで
error: invalid use of member (did you forget the '&' ?)
というエラーが出てしまいます。
プライベートメンバ関数の
threadRoutine
を
void threadRoutine(void* pParam);
と宣言するところを
static void threadRoutine(void* pParam);
にすると、コンパイル可能なようなのですが、今度は、そのメンバ関数内で、staticではないメンバ変数が使えなくなってしまいます。
どのようにすればよいのでしょうか?
737 :
736:2005/07/05(火) 10:06:02
(THREADFUNC)、tidはそれぞれ
typedef void *(*THREADFUNC)(void *);
pthread_t tid[threadnum];
です。
○| ̄|_ ̄|○ <スレッドよりもC/C++の勉強をしたまえ!
○| ̄|_ ̄|○
これって、ルイ14世のAA?
○| ̄|_ ̄|○ <私は哲学者だ。デッドロックは許さん。
○| ̄|_| ̄|○
○| ̄|_ ̄|○ <か、かあさん!
○| ̄|_ ̄|○ <
>>736は
>>629と同一人物なのか?
なんでこう同じ質問がなんども... _ ̄|○
>>740 こんな感じでつか
Ψ
○| ̄|_| ̄|○
Ψ Ψ
○| ̄|_| ̄|○ ○| ̄|_| ̄|○
Ψ Ψ
○| ̄|_| ̄|○ ○| ̄|_| ̄|○
>>736 関数はstaticにして、クラス内の変数を使いたければ、クラス自体をその関数に
ポインタとして渡すしかない。
>>745 ○| ̄|_ ̄|○ <君もC/C++の勉強をしたまえ!
>>736 Javaつかえ。C++はあまりマルチスレッド向きではない。
748 :
736:2005/07/06(水) 14:25:39
ここは荒れたスレのようですね。他に行きます。
○| ̄|_ ̄|○ <君の悩みはスレッドとは関係ないからC/C++のスレにでも逝きたまえ。
○| ̄|_ ̄|○ <スレッドとスレッドをかけているのは絶対に秘密!
>>750 ○| ̄|_ ̄|○
>>745はクラスをファーストクラスのオブジェクトのように語っておるが…
A| ̄|_ ̄|A <彼はクラスとオブジェクトの区別がついていないのですね。
B| ̄|_ ̄|Bすまん、ただこれが書きたかっただけなんだ
755 :
デフォルトの名無しさん:2005/07/09(土) 02:56:04
C言語+Windows APIを使っているのですが、
最大化やウィンドウのリサイズを禁止するにはどうすればいいんでしょうか?
最小化はそのまま使えるようにしたいのですが…
自分でメッセージ処理すればおk
B| ̄|_ ̄|B <つーか、何スレ違いに回答してんだよ。
758 :
デフォルトの名無しさん:2005/07/10(日) 11:52:37
Linuxオンチなんで、ちと教えてくださいまし。
- Linuxでマルチスレッド・アプリケーションとなったとき、
pthreadは'事実上の標準'もしくは'アッタリマエ'か?
- pthradはLinuxの一部ではないが、たいていのディストリビューション
には添付されている。という認識で正しいか?
- スレッド起こすのにはcloneとかいうsystem-callがあるが、
こいつはコンテキストの切り替えにプロセスと同じことやる
ので決して速くはない。は真か?
上2つは「どのlinuxでも動くようにしたい」ということか?
最後のはよくわからんが普通にスレッド起こすのは十分速いよ。
- 当たり前かつ標準
- pthradは一部でも添付されてもいないが、pthreadは標準
- clone(2)はpthread_create(3)を実現するためのシステムコール。
あんたが使う類いのものじゃない。
>>758 pthreadってのは単なるAPIのこと。
ttp://www.opengroup.org/onlinepubs/009695399/basedefs/pthread.h.html で、UNIX系のOS上でC言語によるマルチスレッド・アプリケーションを記述するのなら、
pthread APIを使うのが「事実上の標準」。
ただし、pthread APIにはオプション的な扱いの関数などがあり、
これらは実装によっては使えないことがある。
Linux上で動作するpthread APIの実装としては、
- LinuxThreads … glibcに取り込まれたため、事実上の標準。
- Native POSIX Threading Library (NPTL) … LinuxThreadsの後継。これもglibcに取り込まれた。
- Next Generation POSIX Threading (NGPT) … NPTLの対抗馬だったが、あぼ〜ん
などがある。
ほとんどLinuxディストリビューションでは、LinuxThreadsかNPTLが使えるはず。
clone(2)ってのは、LinuxThreads、NPTLなどが内部で使ってるシステムコールであり、
アプリケーションプログラマが直接触るものではない。
NPTLもclone(2)使ってるんだ。。。
Win32でとある入出力デバイスをバッファ管理しながら
操作するライブラリ書いてるんだけど、
こういった場合スレッドセーフにするにはどこまでやるべき?
バッファやデバイス設定値を読み書きする所全て排他?
それともTLSでスレッド個別にメモリ確保のみ?
TLSだと複数スレッドから同一デバイスに対して
操作するときどうなるかわからんけどこれで許してもらえるかな?
仕様には特に明記されていないので、
俺様ルールでいいのかなとも思うんですが、
やっぱり普通はスレッドセーフにしないと駄目ですよね。
デバイスへのリクエストが同期式の場合、
(つまりリクエスト呼び出し復帰時に結果が返る)
排他が必要な場合が結構ある。
>>763 どこまでやるべきかは、前提とすべきスレッディングモデルの定義による。
話はそれからだ。
どうしてこれは途中でデッドロックしてしまうんでしょう?
printfなどをmutexでロックしても同じでした。
初歩的なことかもしれませんが、よろしくお願いします。
#include <stdio.h>
#include <pthread.h>
void *ThreadFunc(void *pdata)
{
int i;
for (i = 0; i < 10; i++) {
printf("%c", *(char *)pdata);
}
return NULL;
}
int main(void)
{
int i;
pthread_t pthId;
char a[10];
for (i=0;i<10;i++) {
a[i] = i + '0';
pthread_create(&pthId, NULL, ThreadFunc, (void *)&a[i]);
}
for (;;) {
;
}
return 0;
}
fflush(stdout);
とかいうオチじゃないだろうな
768 :
766:2005/07/14(木) 02:21:27
>>767 ありがとうございます。
やってみたのですが、バッファリングの問題ではないようです。
書き忘れましたが、どうやらスレッドが終了(return)するとロックするようなのです。
ネットにあるような単一スレッドのサンプルは問題なく動いています。
_beginthreadを使った場合はこのようなことは起こりません。
なんでだろう・・・。
joimしてない?
>_beginthreadを使った場合はこのようなことは起こりません。
つまりCreateThread使ってるってこと?
Cランタイムライブラリを使う場合は_beginthreadを使う必要があると思うんだけど
てゆうか
for (;;) {
;
}
ってなんだよ。
MSDOSならともかく、今時のOSで許されるコーディングじゃないぜ。
773 :
766:2005/07/14(木) 08:37:48
>>759 返り値のIDを使わないからです。
配列にして個々にIDを入れても固まってしまいます。
>>770 メインスレッド側はjoinが必須なんでしょうか?
一応joinしてみたのですが、やはり固まります。
>>771 process.hの_beginthreadを使っています。
先ほど
>>770さんに指摘されたjoinなどについて調べて、
結果的にはdetachを使用することでテストケースの場合はロックすることはなくなりました。
が、本件の方はdetachしてもロックしてしまいます。
もう少し調べてみます。
joinしてもダメだったコードをさらせ。
for (i = 0; i < 10; i++) {
printf("%c", *(char *)pdata);
}
fflush(stdout); <-- これ付け足したら動く予感
>>768 > > 書き忘れましたが、どうやらスレッドが終了(return)するとロックするようなのです。
お前の言いたいのは、
・出力されません
に過ぎないのと違うのかと…
「ロック」言いたいだけと違うんかと…
forでビジーループしちゃいかんだろ、スレッドで。
for( ; ; ) {{
sched_yield();
}
ってして他のスレッドを動かすのが基本。
○| ̄|_ ̄|○
>>777 > ○| ̄|_ ̄|○
○| ̄|_ ̄|○ <お前が喋れよ。登場するだけかよ!
>>777 おいおい、それもビジーループなんだよ。
待ってるだけなら pthread_join() を使うのが基本中の基本。
大丈夫かホントに。
780 :
766:2005/07/15(金) 01:36:12
NTでpthread、がとりあえず不思議。
NetBSD でやったら "End" まで出たよ。
>>781 と同感なんだがどうやってるの?
cygwin?
Linux 2.6も問題なし。
>>766 ○| ̄|_ ̄|○ <Win2kのcygwinで実行したところ一瞬で終了して以下が表示された。
01021304215360742819536074281953607428195360742819536074281953607428195360742819
53674289536748956789End
785 :
766:2005/07/15(金) 09:35:41
仰る通り、Cygwinです。
マズイな、こりゃOSを疑うべきなのか。
それが分かっただけでも収穫です、どうもありがとうございました。
OSつーかCygwinの問題だろう。
Cygwinは「UNIXと同じソースで動いたらラッキー」ぐらいのものだと思っ
といたほうがいい。
いやそうなんだが、まさかこういう基本的なところでダメだとは驚いた。
コンパイルできないのはOKだが、誤動作は勘弁してほしいな。
Windows 使う場合は Windows の native thread を使えってことか。
まあ、API は pthread とそんなに違わないから (というか、たぶん
両方とも Mach の cthread の真似だよね、きっと)、wrapper ライブ
ラリ書いて pthread と Windows のどちらでも動くプログラムにする
のは難しくないよ。
つうかNTはもうよせ、と
cygwin、
>>784で動いているやん。
つうかstdoutの排他は?
>>784で正しく動作しているように見えるけど何が問題なの?
Win2kでは動くけど「NT4sp6、デュアルプロセッサ」では動かないということでわ?
というかstdout排他してないし…
こんなのはたまたま動いているだけのプログラム。
OSを疑うとか片腹痛い。
>>780のコードは回りくどい方法だけど一応stdoutを排他制御してますやん。
OSを疑うのはどうかと思うが。
cygwinを疑うのは正しい姿勢の予感。
cygwinはイロイロやってそうだしなぁ
>環境がNT4sp6、デュアルプロセッサです。
ってのに妙に引っかかるな。
デュアルプロセッサで、デュアルプロセッサカーネル使っていないとか
実は、cygwinはデュアルプロセッサに対応していない。とか
> cygwinはデュアルプロセッサに対応していない
さすがにそりゃねーべ
今NTで十分テストされているとはあんまり思えないんだが、そのへんかな
>>784だが、
うちのWinマシンはデュアルではないけどHTです。
OSからはCPU2個に見えてる状態。
cygwinて、glibc?
なんかstdioの排他とかゆってる人いるけど、
glibcのstdioって、スレッドセーフじゃないの?
>801
glibc じゃなくて newlib のはず。
newlibはデュアルに対応していないというのが俺の評価。
スピンロックによる排他制御のために
x86のxchg命令によるatomicなtest&setを使っているが
これがlockプリフィックスつきでないからね。
newlib/libc/sys/linux/linuxthreads/machine/i386/pt-machine.h
のlong int testandset(int *spinlock)を見よ。
cygwinがnewlibのlinuxthreadをつかって
pthreadを実現していたらだめだろう。
これがx86 linuxというconfigureでのみ使われているんなら
関係ないんだろうけど。
それとは別にcygwinにはpthreadの実装があるから関係無いとは思うが。
正直その辺りの関係は俺もわからん。
/* Spinlock implementation; required. */
PT_EI long int
testandset (int *spinlock)
{
long int ret;
__asm__ __volatile__(
"xchgl %0, %1"
: "=r"(ret), "=m"(*spinlock)
: "0"(1), "m"(*spinlock)
: "memory");
return ret;
}
○| ̄|_ ̄|○ <ダメじゃん。 >>newlib
あれ?xchgはLOCKプレフィクスなしでもメモリ相手ならロックかますと記憶してたが。。。
806 :
803:2005/07/19(火) 01:04:02
【初心者歓迎】C/C++室 Ver.20【環境依存OK】
http://pc8.2ch.net/test/read.cgi/tech/1121644782/62 にて質問しましたがこちらのスレッドのほうが適切だと思いますのでこちらで質問させてください。
今gcc3.3.3にてスレッドを利用したプログラムを作成しようとしています。
5回程度のスレッド生成はうまくいきますが
Segmentation fault (core dumped)
が表示されてエラー終了してしまいます。
原因が分かりません。
どこがエラーの原因か指摘していただけませんか?
ソースは以下の通りです。
void *thread_test(void *tmp)
{
struct testarg baa;
//終了時にリソース割り当てを解放
pthread_detach(pthread_self());
baa.id = ((struct testarg *)tmp)->id;
baa.cmd = ((struct testarg *)tmp)->cmd;
free((struct testarg *)tmp);
printf("++++++++++++++++++++++++++++++++++++++++\n");
switch (baa.cmd){
case 1:printf("good morning\n");break;
case 2:printf("hello world\n");break;
case 3:printf("good bye\n");break;
default:printf("oh no!\n");break;
}
printf("++++++++++++++++++++++++++++++++++++++++\n");
return (NULL);
}
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct testarg{
int cmd;
int id;
};
void *thread_test(void *);
int main(void)
{
struct testarg *foo;char ss[80], *p, *pp;pthread_t threadID;int i = 0, j = 0;
for(;;){
j++;
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("%d回目\n", j);
//メモリ確保
if((foo = (struct testarg *)malloc(sizeof(struct testarg))) == NULL){
puts("malloc() error");
exit(1);
}
//自動操作
i %= 3;sleep(3);
foo->id = i;foo->cmd = i;i++;
//デバッグ用
printf("foo\nid = %d\ncmd = %d\n", foo->id, foo->cmd);
if(foo->id == -1)
break;
//クライアントスレッドを生成
if(pthread_create(&threadID, NULL, thread_test, (void *)foo) != 0){
puts("pthread_create() error");
exit(1);
}
printf("with thread %ld\n", (long int) threadID);
if(i==100)
break;
}
puts("good end");
return 0;
}
>>807 うちでは落ちないでいつまでも動き続ける。
gcc は 3.3.5。
pthread_detachをメイン側でやれば落ちないみたい
812 :
807:2005/07/24(日) 23:12:26
mainでpthread_create()の後にpthread_detach()を挿入し、
thread_test()の中のpthead_detach()を削除することで解決しました。
>811さんありがとうございます。
すいませんが、一つ疑問があります。
pthread_create()の引数が取ってきたpthread_t型の変数で正しい値ならば
pthread_detach()はいつでもどこの関数でやってもいいんでしょうか?
>810さんありがとうございます。
いまバージョンアップ中です。
gcc 3.3.5にしたらどうなるかも報告したいと思います。
あと、一応私が書いたソースにはバグはなく、
Segmentation fault (core dumped) で落ちてしまうのは
gcc ver 3.3.3のせいだと考えてよいのでしょうか?
落ちるのは gcc というより pthread の実装の違いかも。
814 :
807:2005/07/25(月) 20:32:29
struct testarg{
int cmd;
int id;
pthread_t threadID;
};
として、
if(pthread_create(&foo->threadID, NULL, thread_test, (void *)foo) != 0){
・・・
}
void *thread_test(void *tmp)
{
struct testarg baa;
//終了時にリソース割り当てを解放
pthread_detach(((struct testarg *)tmp)->threadID);
・・・・・・
}
としたら問題が解決しました。
pthread_self()の問題だと思いますが、
原因はよくわかりませんでした。
失礼しました。
815 :
デフォルトの名無しさん:2005/07/26(火) 00:33:54
pthreadを使ったマルチスレッドプログラムで、
あるスレッドがfcntlでファイルをロックしているとき、
同じプロセスの別のスレッドが同様にロックをしようとすると、
ロックが取得できてしまうんですか?
>>815 fcntlはロックの所有権がプロセス単位だから。
817 :
デフォルトの名無しさん:2005/07/29(金) 22:40:15
age
818 :
デフォルトの名無しさん:2005/07/29(金) 23:05:36
マルチスレッドセーフとは
1.スレッドの中でスレッドを作成した場合にいうのでしょうか
2.一つのプロセスで複数のスレッドを作成した場合にいうのでしょうか。
それとも両方マルチスレッドセーフというのですか?
1と2をどう区別していいのか教えてくれ。
スレッドセーフの意味わかってるのか?
821 :
デフォルトの名無しさん:2005/07/29(金) 23:34:22
1.
pthread_create(&threadID0, NULL, func0, (void *)foo);
pthread_create(&threadID1, NULL, func1, (void *)fooo);
func0()が実行されている間にメインスレッドにて新しく他のスレッドが作成される。
2.
void *func0(void *arg)
{
pthread_t theadID2;
pthead_create(&threadID2, NULL, function, (void *)arg);
}
メインスレッドから呼び出されたfunc0()の中で別のスレッドを作った。
こういうのを考えて818を書きました。
,j;;;;;j,. ---一、 ` ―--‐、_ l;;;;;;
{;;;;;;ゝ T辷iフ i f'辷jァ !i;;;;;
>>821 お前にはマルチスレッドは無理。
ヾ;;;ハ ノ .::!lリ;;r゙
`Z;i 〈.,_..,. ノ;;;;;;;;>
,;ぇハ、 、_,.ー-、_',. ,f゙: Y;;f そんなふうにかんがえていた時期が
~''戈ヽ `二´ r'´:::. `! 俺にもありました
826 :
821:2005/07/29(金) 23:55:01
,j;;;;;j,. ---一、 ` ―--‐、_ l;;;;;;
{;;;;;;ゝ T辷iフ i f'辷jァ !i;;;;; 2chネラは真面目な人が多い
ヾ;;;ハ ノ .::!lリ;;r゙ 人を馬鹿にするようなことはないだろう
`Z;i 〈.,_..,. ノ;;;;;;;;>
,;ぇハ、 、_,.ー-、_',. ,f゙: Y;;f そんなふうにかんがえていた時期が
~''戈ヽ `二´ r'´:::. `! 俺にもありました
828 :
デフォルトの名無しさん:2005/07/30(土) 00:12:37
>181わぁ、書き方を間違えただけであって、正確にはだな、
マルチスレッドセーフを冒すのは、
1.〜
2.〜
それとも両方マルチスレッドセーフを冒すのでしょうか?
だと、思うのは俺だけか?
俺は、1.2.ともその可能性をはらんでいると思う
お互いを蝕むのを避けるために、踏切りの警報灯のように交互にチカチカ同期採る手法や
片方をlockさせる手法があるのでしょう
>181は気にすることはない
リアルで溜まったウサを晴らしたいヤシが吐き捨ててる場合もあるんだから
そういう肥溜めはシカトしときゃいい
∋oノハヽo∈
( ´D`) 誤爆れすか?
@| ̄|_ ̄|@ <ある関数が、複数のスレッドから同時に実行されてもハラハラしない時、
A| ̄|_ ̄|A <その関数はスレッドセーフである、とかなんとか言われるのである。
B| ̄|_ ̄|B <きっとね!
>踏切りの警報灯のように交互にチカチカ同期採る手法
は、誤解招くから、補足しとくと、
お互いがどこまで進んだか分からないと、迂闊にお互いのデータを使えないから、同期を採って、進行度を相互確認する
それと、親プロセス、子プロセスの関係の、マルチプロセス、要はforkというのもあるけど(知っているかもしれないけど)、
これの弱点は、同じOSのshell上で動くから、処理が重くなる。だから、マルチスレッドが推奨されてるわけだけど、
利点もあって、親が終了しても、子は動き続けられる
○| ̄|_ ̄|○ <いいからもう寝ろ
なんで、そんなにうなぎ連結してんの? キモイよ?
一つだと、四つん這いと間違えるから。
pThreadでロックをある所有が行い別のやつがアンロックを行うって方法を
使っているのですが、とても微妙な使用方法だと思うのですが改善する方法ないですか?
あとpthreadのデバッグってどうしてますか?
> 一つだと、四つん這いと間違えるから。
わらた
840 :
デフォルトの名無しさん:2005/08/02(火) 20:41:39
誘導されてきました。
C言語でマルチスレッドプログラミングについて教えてもらいたいです。
問題は、
(1)簡単なスレッドプログラミング及びスレッドの動作について解説せよ。
(2)相互封鎖や相互実行が起こるプログラムを作成し、その動作を解説せよ。
(3)マルチスレッドで、turnやflagを使った排他制御のプログラムを作成し、その動作を解説せよ。
(4)消費者・生産者問題のプログラムを解説せよ。
です。宜しくお願いします。
841 :
デフォルトの名無しさん:2005/08/02(火) 20:44:01
見事な教えてクンぶりに感動すら覚えた。
誘導先でも煙たがられてるし...
グローバル変数や静的変数をスレッドごとに持たせることって可能ですか?
変数をロックして共有するのではなく、メンバ変数みたいな感じで状態管理に使いたいんです。
errornoとかはそうなっているみたいなんですけど。
>>543 TLS
ちと調べればすぐわかりそうな気がするが。
単純にぐぐるとネットワーク関連の方がひっかかるので補足しておくと、Thread Local Storage な。
C++で組んでたときはあんまり意識せずに書けたな。メンバ変数はデフォルトではインスタンスローカルだから
Cでも単純にスレッドごとに構造体のインスタンス別々にしてやればいいジャンとか思うの俺だけ?
まあポインタで引っ張り回したら何だって出来るんだけど、
スレッド内関数呼び出しのそのレベルでも、
スレッドローカルな大域変数のように扱えるのが、
スレッドローカルストレージフレームワークだから…
Common Lispの*special*変数も似た風に使えるけど、
あれよりはコストが安い。
( ´∀`) 気のせいダロ
>846
>最近のC/C++標準では __thread というキーワードで言語仕様にも採り入れられている。
9899:1999 でも 14882:2003 でもそんなキーワードは引っかからないぞ。
つーか、__ で始まってる時点で処理系依存の拡張じゃないのか?
>>846は、gccのドキュメントの以下の部分を誤読しているんだろう?
C99を__threadで拡張するとすると標準文書はこう変更されるってことなんだけど。
>5.51.1 ISO/IEC 9899:1999 Edits for Thread-Local Storage
>
> The following are a set of changes to ISO/IEC 9899:1999 (aka C99) that
> document the exact semantics of the language extension.
852 :
846:2005/08/06(土) 19:43:25
gccの__threadってなんなの?
int pthread_key_create(pthread_key_t *key, void (*destr_function) (void*));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *pointer);
void * pthread_getspecific(pthread_key_t key);
のsyntax sugar?
スレッドプロシージャをクラス内に実装する裏技(といっても常套手段)使えば
大域変数みたいに使うことはできる。
てかCreateThreadに渡すダミーのスレッドプロシージャにthisポインタ渡してメンバ関数を起動するだけだから。
(Win32での話)
さんざん既出かもしれないけど、質問します。
windowsでpthreadの状態変数みたいなのはどう実現すればよいのでしょうか?
排他変数にMutexをつかうならSignalObjectAndWaitをつかえばよいんだけれども
CriticalSectionを使いたいんです。
状態変数に近いのはイベントオブジェクトじゃない?
状態遷移マシンの実装を語るスレがほしいな。
>>858 ○| ̄|_ ̄|○ <オマエ「状態遷移マシン」て言ってみたかっただけだろ!
正規表現ライブラリのソースをみるとか
マルチスレッド関係ないな
861 :
856:2005/08/07(日) 13:18:58
> 状態変数に近いのはイベントオブジェクトじゃない?
そうなんですけど、pthreadの場合、 状態変数をwaitするとき
mutexを渡して内部でアトミックにmutexをアンロック→シグナル待ち→mutexのロックをしてて
これをwindowsで実現できないかなと・・・
WindowsのばあいMutexをWait〜系関数で待つことは出来るけど、CriticalSectionは使えない。
たとえばpthreadで状態変数をつかっているようなところを
windowsに移植するときはどうしたらよいのかなと思いまして・・・
862 :
856:2005/08/07(日) 13:20:21
> 状態変数に近いのはイベントオブジェクトじゃない?
そうなんですけど、pthreadの場合、 状態変数をwaitするとき
mutexを渡して内部でアトミックにmutexをアンロック→シグナル待ち→mutexのロックをしてて
これをwindowsで実現できないかなと・・・
WindowsのばあいMutexをWait〜系関数で待つことは出来るけど、CriticalSectionは使えない。
たとえばpthreadで状態変数をつかっているようなところを
windowsに移植するときはどうしたらよいのかなと思いまして・・・
aprだと、EventとMutexを使ってcond_wait/signalをエミュレートしてるね。
もちろん、cond_waitに渡すmutexはCRITICAL_SECTIONで良くて、
Mutexを使っているのはWaitForで待つためらしい。
http://apr.apache.org/
864 :
デフォルトの名無しさん:2005/08/07(日) 14:18:12
クラス内のメソッドを並列で実行したいのですが、やり方がわかりません。どこかに参考になるページはありませんか?
865 :
856:2005/08/07(日) 14:46:06
>>863 ありがとうございます。参考になりました。
どうやらcondに渡すのはCRITICAL_SECTIONみたいだけど、
cond内部でMutexを持っていてそれを用いて排他制御を行いつつ、
CRITICAL_SECTIONアンロック→シグナル待ち→CRITICAL_SECTIONロックしているみたい。
(apr-1.1.1\locks\win32\thread_cond.c)
>>859 ばれたか。
でもWindowsでWindowMessageを使って実装する例とか、
専用のクラスの実装例とか、どんな問題があってどんなメリットがあるとか
そういうことを勉強したかったのもあるよ。
pthread_cond_signal/broadcastの実装には
シグナルとウエイトをアトミックにやる必要がある。
「アトミックに」ってところが重要で
シグナルしてウエイトするというようにバラバラやっていたのではダメ。
それをする手段は、Win32だと、SignalObjectAndWaitしか知らん。
?
mutex といえば、Boost.Thread の Win32 版 mutex の実装に、
CRITICAL_SECTION ではなくて、Mutex が利用されていたな。
Win32 の Mutex は遅いから、メータードセクションを利用して
実装して欲しかった。
>>869 今1.32のソース見たけど、クリティカルセクション使ってたよ
>>869 メータードセクションってこれ何時頃から実装されてるの?
MSDNみて、こんなの有ったのかと目から鱗状態なんだけど。
95でも使えるっぽいから、相当前からある様なんだけど。
自己レス。
APIとしてSDKに実装されてるわけじゃないのね。
MSDN英に.hと.cのフルソース上がってたからもらってきた。
mutexと置き換えて遊んでみる。
>>869ありがと。
うろ覚えだが、メータードセクションは、ロックカウントを持っていないので、
クリティカルセクションのつもりでリソースを1にして、
同じスレッドで複数回 EnterMeteredSection すると、あとあと面倒だったかも。
メータードセクションなんで初めて知ったよ
みなさんスゴイすね
>>873 それなら自分でReentrantな実装にしちゃえば?
メータードセクションのReentrantな実装に改良している最中に、
以前AdvancedWindowsのオプテックスを
セマフォ的にしたものを作ったのを思い出した。orz
とても不毛な月曜の午前。
877 :
デフォルトの名無しさん:2005/08/26(金) 14:48:45
基本的な質問します。
stringとかのポインタをスレッドに渡し、スレッドより先にメインが終了してしまった場合、
そのstringはもう生きていないですよね。
こういうときはどうやって処理をすればいいのでしょうか?
>>877 寿命管理ができないなら、実体で渡す。
実体渡しが嫌なら、サボらずにちゃんと寿命管理を行う。
○| ̄|_ ̄|○ <メインが終了したらプロセス全体が終わるだろ
880 :
デフォルトの名無しさん:2005/08/26(金) 15:11:45
がんがって実態渡ししてみます。
メインが終了したらアプリ全体が終わっちゃうから、
スレッドでの処理が終わるまでメインを待たせろつーの。。
○| ̄|_ ̄|○ < ああ、面倒くせーな!
883 :
デフォルトの名無しさん:2005/08/28(日) 13:15:09
マルチスレッドアウトな関数multithreadout()があります。
この原因はグローバル変数glbを使っていることです。
通常、同一プロセス内でmultithreadout()を使うと駄目ですが、
multithreadout()をdllファイルにしてもマルチスレッドアウトのままでしょうか?
>>883 Yes.
DLL(が読み込まれたメモリ空間) はプロセススコープの資源。
はい
解決する方法として
1).マルチプロセスにする。
2).multithreadout()だけをexeファイルにして引数を受け渡す(パイプを使う&dllを使用しない)
3).multithreadout()をdllファイルにし、multithreadout()呼び出し専用の
exeファイルを作り、パイプを使う
2).3).の違いはmultithreadout()が静的か動的かなのですが、
他に解決する方法はありますか?間違った解決方法を考えていませんか?
また、処理のほとんど(90%以上)はmultithreadout()が行います。
呼び出し回数は数回程度です。
グローバル変数を使わないように、multithreadout()を変更する
と言う選択肢もあるはず
multithreadout() を multithreadout_real()
か何かにリネームして、
multithreadout()は、
multithreadout()
{
static CriticalSectionとかMutexとか lock;
Lock(lock);
multithreadout_real();
Unlock(lock);
}
あたりにすればいいんじゃないかと思う。
例外処理とか、lockの初期化は適当に。
889 :
856:2005/08/28(日) 17:35:49
以前紹介してもらったaprのミューテックスなんだけど、よく見ると怪しい部分があるような気がしてきた。
broadcastのときwaitしているスレッドを数えるためにカウントしているんだけど、
イベント待ちの直後そのカウンタをインクリメントする必要があって、その部分がクリチカルになっていない。
どうなんだろう?自分は怖いんでカウンタをCRITICAL_SECTIONで囲んだけれども。
890 :
856:2005/08/28(日) 17:46:49
あう、mutexじゃなくてconditionだった。スマソ
signalとかbroadcast待ってる香具師ってスピンしてんの?
古いイベントで使うようなselectとかとどっちが速い?
×古いイベント
○古いイベント志向
すまそ。
selectって古いイベント志向といういいかたするのか?
ま、それはさておき、遅いか早いかは
実装による。
以上だ!
selectって古いイベント志向といういいかたするのか?
ま、それはさておき、遅いか早いかは
実装による。
以上だ!
896 :
デフォルトの名無しさん:2005/09/02(金) 00:41:56
この読みが外れればそれを口実に日本に戦争を仕掛けるつもりだったのか
↑
誤爆しました。メンゴ
Solarisだと、select(3C)はpoll(2)を使ってる
>>899 それは昔の話で、select(3)の実装がpoll(2)を使わないように2,3年前に変わらなかったっけ?
901 :
デフォルトの名無しさん:2005/09/04(日) 18:49:22
そんな重要そうな事もはっきりしないのがUNIX文化ってやつですね
selectもpollも対して変わらんよ。じゃあ
「イベントとか割り込みって、中でpoll使ってんじゃね?」
と言えばいい?
ちゃんとCPU返してくれればどうでもいい。
たまにビジーループぶん回すのがいるからのう…
904 :
891:2005/09/05(月) 00:08:39
>>903 えっと、まさにそこを聞きたかったんすけど。
ループしてるか見分ける方法ってある?
>>898 んなわけねー(w
>>904 お前以外にループする奴はいない。in お前のプログラム&カーネル。
906 :
891:2005/09/05(月) 23:58:31
何言ってるのかわかんないんだけど。
908 :
899:2005/09/06(火) 21:37:49
Windowsは詳しくないから分からない
というか、こんなの聞いてどうなるものでもないような
>>891 > signalとかbroadcast待ってる香具師ってスピンしてんの?
ロックが競合したときにmutexの入口でスピンすることはあっても、
signalとかbroadcastを待ってる状態(つまり条件変数をwaitしている状態)で
スピンし続けてCPUを離さないってことはありえない。
そんな実装があったら、条件変数の意味が無くなるだろ。
スピンとポーリングって何が違うの?
スピン = 無期限連続ポーリング
>>910 spinってのはSMPで一つのCPUだけがポーリング対象の資源を
得ることが出来るようなポーリングの仕方のことを言う。
皆がアクセスできる皿と、自分の手元の皿を夫々がくるくる入れ替えて
手元に来た皿に肉が乗ってたら食べていい、みたいな感じ。
>>912 一面的な説明で「仕方のことを言う」はいかがなものか。
>>913 文句だけじゃなくて、一面だけというのなら別の面からとか
包括的な説明とか、内容あるレスつけようぜ。
スピンしないポーリングって可能なのか。
スレッドとかシグナルってハードレベルでどうなってるのか
わからなくて効率が全然読めないんだが、
その辺をユーザーレベルで理解できる本、サイトない?
WindowsならAdvancedWindowsという本かな。
これ読むとWindowsでポーリング待ちなんて馬鹿げてると思うはず。
>>916 Windowsよく知らないので、詳しく!
詳しく!
分散OS ”あ萌え場”って何でしょうか?
>>917 「Advanced Windows」嫁
あとは「Win32 マルチスレッドプログラミング」
つーかこの話で本が1冊出来るかもよ
>>915 非SMPではspin lockなど使わずにタダのループによるポーリングで十分
(カーネルモードで、割り込みを考慮しないとして)。
また、競合するスレッド/プロセスがいない場合には、SMPだろうが割り込みが
あろうが単純ループのポーリングで十分。
効率的な点については、spin lock の一サイクルはメモリ<->レジスタ間の
値の入れ替えで完了するので、行儀良く短いクリティカルセクションから
なるコードの場合は(並列度にもよるけど)、わざわざスケジューラをいじって
スレッドをシグナル待ちにするような処理よりも単にspin lockの方が効率が良い。
>>922 > (カーネルモードで、割り込みを考慮しないとして)。
> また、競合するスレッド/プロセスがいない場合には、
殆んどあり得ない仮定を置いて、何を言っているんだが…
>>923 バカ?スピンロックについての話なら、普通割り込みも競合もあるけど、
915は「スピンしないポーリングって可能なのか。」って聞いてるわけで、
単に「ポーリング」って言った場合には
>>922の条件は良く有ることだと
思うけど。
ポーリング儲は糞プロセス量産してんだろうね
ものすごい短時間しか待たないことがわかってるなら、ポーリングの方が効率いいこともあるべ。
>>915 同期無しでただ読むだけで済むように設計すればいい
>>921 Windowz使ってないので、「Advanced Windows」読んでも意味ないし
MINIX使ってないので、「オペレーティングシステム―設計と理論およびMINIXによる実装」読んでも意味ないし
はあ。
Windowsは業界スタンダードだから意味あるはずだけどねえ
何業界だ?
Window業界でのはなしでしょう
windowsのイベントや、UNIXのsignalは、プログラマからみれば
APIとしてはコードのその場所でじっとwaitしてる形になると思うけど
イベントやsignal自体の内部実装(カーネル側?)
では結局はポーリングで実現されてたりするわけ?
エロゲー的にはポーリングが正義、というFAが出ておりますが何か?
割り込みにきまってんだろハゲ
>>933 イベントやシグナルみたいな大掛かりなものはスレッド自体が
待ち状態になってスケジュールしなおされる。
スピンロックで待つのはWin32でSMPのEnterCriticalSection(記憶違
いかも)とか、Windows の WDM のコードとか、linux のカーネル内の
コードとかでスケジューラを動かすまでもないホンのちょっとの排他
処理を行うとき。
なるほろ
今2wayの鯖あるのですが、2つのCPUを効率よく使って計算させようと思うと
スレッド間でメモリ共有するだけでいいでしょうか?何か気をつけることないですか?
意味若乱
逆になるべく共有リソースを無くして独立させる方が良いと思う。
共有してると、アクセス排他制御とか同期制御とかが絶対必要。
ていうかスレッドはメモリを共有してるもんでしょう
>>942 メモリ空間は共有してても、同じメモリアドレスを共有してなきゃ問題ないじゃん。
>>943 財布は共有してても生活空間は共有しない
という独立思考の高い夫婦モデルだな
まあ普通プロセス/タスク内のスレッド間ではメモリを共有してるけどな。
>>937 なんか変じゃない?
スレッドがスケジューリングされなきゃ、何時まで経っても他スレッドが実行されず、
状態が変化しないのと違う?
>>946 完全に協調型ならそうなりますな。
普通は外的要因で叩き起こされると思いまふが。
元の質問も、その答えも、高度すぎて意味がわからん
要するに、
>>937 > スケジューラを動かすまでもない
を「自分からyeild()しないで」等に書き直した方がいいって事ね。
そもそもSMPでスケジューラ等を実装するには、
スピンロック等の低レベルな排他機構が必要なわけで…
マルチスレッドと、ウィンドウプロシージャについて質問なんですが、
現在、通信系のプログラムを書いています。
あるデータを受信したら処理をして、その結果を送信元に返信する。
という関数があるのですが、
1).スレッドを作り、そのスレッドで処理をさせる。
2).ウィンドウプロシージャを作り、メッセージにデータのポインタを渡す。
ウィンドウプロシージャで処理を行わせる。
この2通りを考えてみたんですが、楽なのは2)です。
どっちの方法が有効でしょうか?
スレッドを使ってブロッキングでやるのが1番楽だと思う
こんにちは。
gcc(RHEL), MinGW(Win), Visual Studio .NET(Win)の各環境でC++を使って私用ミニツールなど
を作ったりして仕事してる、一介の営業マンです。最近はサービスでお客さん用のツールなんか
も作ったりし始めました。SE受注減らしてどうするんだって感じですが。
C/C++でのpthreadに関する質問です。
pthread_createでガーっと並列にスレッドを作って仕事をさせ、pthread_joinを回して終了を待つわけな
のですが、
pthread_joinはブロックするので、先頭のスレッドが長引いちゃうと後に続くスレッドが先に終わってても
ボケーっと待ってしまいますよね。
これを、スレッドが終了した順に処理する方法ってありますでしょうか?
よろしくお願いします。
例えばこんな風にすればいいんじゃない?
* 生きてるスレッド数を数えるカウンタを用意しておく。(スレッド数で初期化)
* 各スレッドは終わるときにカウンタを減らして、ゼロになったら pthread_cond_signal() みたいなことをする。
* メインは pthread_cond_wait() かなんかで待ち。
* 起こされた時にはスレッドは全部終わってるはず。
* もちろんカウンタをいじるときは排他制御。
あと、スレッドが終わる度になんかするなら、
* 各スレッドは終わるときにカウンタを減らして、 pthread_cond_signal() みたいなことをする。
* メインは pthread_cond_wait() かなんかで待ち。
起きたときにカウンタがゼロになってたら全部終わってるはず。
どうせ全部まとめて終了を待つなら、順番にjoinするだけで何の問題もないと思うけど。
メインスレッドはワーカースレッドを終了を順次待ちつつ何かしてる必要があるなら、
キューを用意してスレッドが終了前に自分のpthread_tを追加するとか、
メインスレッドがイベントループなら終了を通知するイベントを投げるとか。
960 :
デフォルトの名無しさん:2005/09/22(木) 19:33:15
> 全部まとめて終了を待つ
逆です
早く終わったスレッドの順に次のジョブキューに入れるやり方ですね
それならスレッドプールでしょ
元の質問文と真実の内容がかけ離れてんな
>>960 >早く終わったスレッドの順に次のジョブキューに入れるやり方ですね
その場合はスレッド終わっちゃいけないから、joinなんか使えないと思われ
リスト構造にしたらいいんじゃね?
>>963 pthread_cleanup_push()で登録するとか。
966 :
956:2005/09/29(木) 20:31:03
つまりこんなかんじ?
1. 子スレッドはその仕事の最後にグローバル関数で
「俺は終わりましたフラグ」を立ててから死ぬ
2. メインのスレッドは全部の子スレッドの「俺は終わり
ましたフラグ」を監視しながらぐるぐる回ってる
3. あるスレッドの「俺は終わりましたフラグ」が立ったら、
そのスレッドの計算結果を取得して次の仕事に放り込む
んー、スレッドの数が不定なので、俺は終わりましたフラグの
作り方と監視の仕方の実装に工夫が要りそうですね。
>>956 なぜスレッドを使って並列でしようとしてるのかが見えないんだけど・
本当にマルチスレッドにする必要あるのかな
リスト構造でやってみたらと・・・
//スレッドに持っていく構造体
typedef struct tag tag;
struct tag{
tag *next;//初期化してNULLにしておく
・・・
};
//メインが持つグローバルデータ
tag *root;
tag *last;
int flg;
計算が終わった子は
flgが特定の値であれば待機。
flgが特定の値でなければ特定の値にして
rootがNULLでなければlast->nextに自分の構造体のアドレスを登録。
rootがNULLであればrootとlastに自分の構造体のアドレスを登録。
メインスレッドは
flgが特定の値であれば待機。
flgが特定の値でなければ特定の値にして、
構造体のデータを取り出す。
root=root->next;とする。
flgの値を戻す。
ま、こんな感じでどうざんしょ。
>>966 漏れならこうするよ。
メインスレッド
1. ジョブをキュー(FIFO)に登録。
2. ワーカスレッドを妥当な数だけ生成
3. pthread_cond_wait() か何かで待ち、ジョブのキューが空になっていたら完了。
ワーカスレッド
1. ジョブをキューから取り出して実行
2. 完了したら、その結果を利用した「次の仕事」を(もしあれば)ジョブキューに入れる。
無ければスレッド終了。
3. 1に戻る
pthread_cond_waitとかpthread_cleanup_pushとか、クレバーなコーディングはご法度
クリティカルセクションとミューテクスはどちらがお勧めなのでしょうか?
ダンディーな方、教えてくださいませ。
>>972 オススメと言うか、その2つは使い分けるもの。
Win32の場合の話だけど、
プロセス内でのスレッドの同期程度ならクリティカルセクションを用いる。
複数のプロセスで排他を行いたいなら、ミューテックスの類を使う。
SMPで無ければ効率は同じ。SMPの場合にはInitializeCriticalSectionAndSpinCount の説明を参照。
>>973さん
なるほど、納得しました!
どうもありがとうございました。
>>974 まだあった・・
複数の同期オブジェクトを待ったり、待っている最中にWindowメッセージや
COMのLRPC(外部スレッド/プロセスからのCOM呼び出し)を処理する必要
があるなら Mutex。
>>975 色々違いがあるんですね。
ご丁寧に有難うございましたm(_ _)m
977 :
デフォルトの名無しさん:2005/10/11(火) 23:14:03
age
お舞らたとえばですがファイルの内容をメモリ上に展開しそこにほかのスレッドがアクセスする必要があるとしたらどんな風に書きますか?
・データは木構造
・IOからメモリに展開するスレッドは複数
・そこにUI スレッドや、計算スレッドが頻繁にアクセスする。リーダーとライターが複数ずついる。
・ためしにクラスレベルロックみたいのでやったらUIスレッドでCPUが100%言ってないのにたまに固まる(1秒以下)ことがある。
こういう場合ってどんな風にするもんなんでしょう。粒度さげると書くのが('A`)マンドクさくなるしデッドロックの危険も出てくる。
一般解や俺ならこうしてるってのがあればよろ。