[過去ログ] マルチスレッドプログラミング相談室 (986レス)
上下前次1-新
抽出解除 レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
736(56): 02/11/12 19:32 AAS
Windowsであるクラスに参照カウントを持たせ、InterlockedIncrement./InterlockedDecrementで
マルチスレッド対応にしようとしたのだが…
void ref() {
InterlockedIncrement(&m_ref);
}
void release() {
if (InterlockedDecrement(&m_ref) == 0) {
delete this;
}
}
ところが、delete thisの直後にref()が呼ばれると、m_ref自体が解放された領域にあるため、
とんでもない値になってしまう。参照カウントをメンバー変数にするのが間違い?
どうしたらいんだろう?マルチスレッドのエキスパート様の降臨おながいします
739: 736 02/11/12 21:18 AAS
ある時点で、m_ref>0だったとします。
2つのスレッドが、それぞれ同時にref()とrelease()を呼び出すと…
741: 736 02/11/12 21:35 AAS
void ref() {
EnterCriticalSection(&m_cs);
InterlockedIncrement(&m_ref);
LeaveCriticalSection(&m_cs);
}
void release() {
EnterCriticalSection(&m_cs);
if (InterlockedDecrement(&m_ref) == 0) {
delete this;
}
LeaveCriticalSection(&m_cs);
}
としても、ref()でInterlockedIncrement()にたどり着いたときには…
744: 736 02/11/12 22:36 AAS
refが参照カウントを増やす(objectを貰って来る)ためのものなのだが…
746(3): 736 02/11/13 10:05 AAS
いやCOMじゃなくて。
あるオブジェクトのインスタンスが作られるとm_ref=1となっていて、
そのオブジェクトを例えば別のスレッドが使うためにコピーを作るとm_ref=2
となる。
まさにその瞬間に、インスタンスの元のホルダーがオブジェクトを破棄しようとすると、
m_refのインクリメントとデクリメントが同時に起きる。
Interlocked...は同時じゃないが、ref()とrelease()が同時に呼ばれrelease()を
実行しているスレッドの方が早くCriticalSectionを獲得して解放したのち、
InterlockedIncrementが呼ばれると、解放されてしまうので値が不定になってしまう。
752(2): 736 02/11/13 12:37 AAS
>746
やっぱり、そういう事になりますか。
>749
それは、ちっとも解決にならない。
method2がこの場合ref()なわけで、ref()から戻ったら、そのオブジェクト使おうと
するんだから。
>750
参照カウントは、扱われるインスタンス内に有りますが、
そのインスタンスを指すスマートポインターのようなクラスで持たなきゃならないって
事ですか?
そうでなくて、インスタンスと別にアロケートして参照カウント作ってもだめって事だけ?
>グローバルなオブジェクトや静的なオブジェクトを参照カウントでやろうとしてるような気もするし。
流石に、そんなこたぁない。
757(1): 736 02/11/13 17:30 AAS
なんか昨日から粘着が居るが
>753
>分からんヤツやな、、、
あんたほどでは(W
>refする前に、oobjectが生きてて、refできるか確かめないかんやろ。
確かめた時生きてても、じゃあ参照しようとしたら死んでる罠
確かめるときに参照かうんと増やす何て言うなよ(W
>755
>参照が増減するたびに必ずカウンタも同期しなきゃ行けないってこと、わかってる?
それは当然ですね。
>これは本来アトミックな処理なので、別スレッドに渡すってのも
別のスレッドに渡すのではなく、
あるスレッドAが参照カウントを持つOのインスタンスをつくって、
別のスレッドBがそのオブジェクトをもらおうとしたらば、
Aはもう要らないとOを破棄しようとしている最中だったわけです。
760(3): 736 02/11/13 18:22 AAS
>「渡す」つってんのはインスタンス自体じゃなくて参照のことをいってんだけど。
>ポインタといったほうがいい?
「渡す」というのは、あるスレッドAがインスタンスOの参照(カウントが増えた状態)を、別のスレッドB
がアクセスできるようにするという意味で使いました。
そうではなくて、スレッドAの預かり知らぬところで、スレッドBがインスタンスOを
コピー(の過程で参照化運とは増える)して使おうとするということです。
参照を受け取った時には、当然参照カウントは増えていますが、Oの参照カウントを
(クリティカルセクション獲得後)増やそうとしたら、スレッドAが解放してしまっていた
わけです。
>758
そういうなら、参照カウント使ったクラスうpしてみそ。逃げますか?(W
763(1): 736 02/11/13 19:03 AAS
そんなに広い範囲でロックかけないで済む方法ってないの?
767(1): 02/11/13 21:20 AAS
>>736
参照カウントが 1 のオブジェクトを複数のスレッドから参照してる時点で、
ref を呼び忘れてる。
参照回数0 のオブジェクトに到達することが正しい振る舞いだとしたら、
それは通常の参照じゃなく、弱い参照だ。
768(1): 02/11/13 23:15 AAS
>>736
そもそも、スレッドが生きているかどうか分からないオブジェクトへの
ポインタを受け取ること自体に問題があるような。まさか、
スレッドA:
p = new クラス();
Bに渡す(p);
p->release();
スレッドB:
p = Aから受け取る();
p->ref();
というコードを書いていないだろうな?もしそうなら構造上の問題。
Bから見える場所にpを格納したなら、その分の参照カウントを数えなくては
ならない。それって本質的にはシングルスレッドでも同じことだけど。
783: 736 02/11/14 10:50 AAS
どうして、参照カウントが増えた後の話にしたがるのか…
787: 736 02/11/14 11:26 AAS
>>773
> そりゃカウントミスってる。AがOを持ってるところでBがOの参照を受け取って
> カウントも増やしたんなら、カウントは2以上のはずだ。その状態でAが解放し
> てしまうというのはバグ。
はぁー。
受け取る処理ってどうやるのさ?
>774
これからよく読んでみます。
ありがと。
789(5): 736 02/11/14 11:34 AAS
O1は、スレッド間で共有しているリスト中の要素としてある。
O2=O1は、そのリストから目的の物を検索して取り出す処理の中。
794: 736 02/11/14 12:31 AAS
>791
>その前にThread Bがリストの要素への参照を持ってるなら
>参照カウントは2になってなきゃおかしい。
リストの要素への参照とは?
O1がそれだと言っているのか(W
>793
>で、この get と remove はロックを使わずやりたいと。
>そういうことか?
そう。
でも、
>「排他制御せずにリストにアクセスしたら、変になるんですけど。」
という事じゃない。
removeで要素中のO1は削除されるけど、Thread BがO2を手に入れていれば
O1-+
+-->ref:2,data:"ABC"
O2-+
から
O2---->ref:1,data:"ABC"
となり、他のスレッドは、もはやこのデータにアクセスできないが、
Thread BはO2から使える。O2が不要になって破棄したら、データ本体も解放される。
800: 736 02/11/14 21:27 AAS
>796
未だに問題のポイントがわかってない言語障害者が居ますね。
>797
やっぱり、そうなっちゃいますかね。
>799
COMは関係なかろう、STAならInterlock何かする必要無いし、
そうでなければ、COMでも同じ。
804(1): 02/11/14 22:20 AAS
>>736
考え方おかしいよ。
管理する側とされる側がごっちゃになってる。
そもそもdelete後に破棄されたインスタンスの排他制御
オブジェクトを参照しようとしてる事をおかしいと思わないの?
809(1): 736 02/11/15 10:43 AAS
>804
頭おかしいよ。
こんなのどこにでもある。見たこと無いのか?
810: 02/11/15 10:55 AAS
>>736
何人もの人間が否定してるんだから、おかしいのはお前だろ(笑
811(1): 736 02/11/15 11:23 AAS
じゃあ、COMもおかしいのか?
813(2): 736 02/11/15 12:24 AAS
>812
>つーか、教えを乞う立場だったら、もっと謙虚になれ。
共有しているオブジェクトの集合に丸ごとロックかけずに、
各オブジェクトの参照カウントだけで済むかがポイントなのに、
参照カウントのインクリメント不足だとか、
COMを知ってればとか、
おんなじ事 おんなじ事 おんなじ事 おんなじ事 ばかーーーり。
しつこつ しつこく しつこーーーーく 同じこと繰り返す粘着が多くてウンザリ。
getはアトミックだとか…あのなあ、それ自体はアトミックでもremoveとgetを同時に呼ぶことは出来るんだよ。
参照を持っているならとか…あのなあ、その参照を受け取るのがgetだろ。共有オブジェクトのgetなんだよヴォケ。
じゃあ、参照を手に入れる処理を書いてみろというと、とたんに逃げ出す。
どうしてポイントがずれた香ばしい奴が多いのか。
814: 736 02/11/15 12:26 AAS
>812
>「どこにでもある」 が 「おかしくない」 の理由には全然ならない事に気付け。
>つーか、そんなのそうそう転がってないはずなんだが、あんたよっぽどクソな
>サンプルに見舞われてるんだな。
これ見たこと無いか?
static ULONG WINAPI Increment(LPLONG p) {return InterlockedIncrement(p);}
static ULONG WINAPI Decrement(LPLONG p) {return InterlockedDecrement(p);}
ULONG InternalAddRef() {
return _ThreadModel::Increment(&m_dwRef);
}
ULONG InternalRelease() {
return _ThreadModel::Decrement(&m_dwRef);
}
STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
STDMETHOD_(ULONG, Release)() {
ULONG l = InternalRelease();
if (l == 0)
delete this;
return l;
}
まあ、君のコードの中では、
static ULONG WINAPI Increment(LPLONG p) {return ++(*p);}
static ULONG WINAPI Decrement(LPLONG p) {return --(*p);}
しか使われないと思うが(W
816: 736 02/11/15 12:40 AAS
それで?
818: 736 02/11/15 12:44 AAS
738 :デフォルトの名無しさん :02/11/12 20:25
参照カウントを0から始めたに100スレッド
740 :デフォルトの名無しさん :02/11/12 21:24
ref() と release() が互いに排他してなきゃ動くわけないじゃん。
742 :デフォルトの名無しさん :02/11/12 21:57
あるオブジェクトに触れるスレッドが一つふえたら
そのオブジェクトの参照カウントをageておく必要があることに
気づいてないに1000はらたいら
743 :デフォルトの名無しさん :02/11/12 21:58
>739
それもなんだかおかしな動作だな。
refを発行する、というのは、どっかからobjectを貰ってきてるわけだろ。
で、releaseを発行するということは、所有権の一端を持っているわけだよな。
それで、deleteが実行されるというのは、
「refcount == 0かもしれないobjectが渡ってきた」
「release発行しすぎ」
ってなわけだろ。refするタイミングとか、考え直した方がいいんでないか?
745 :デフォルトの名無しさん :02/11/12 22:52
736はひょっとしてCOMを知らない?
747 :デフォルトの名無しさん :02/11/13 10:35
「別のスレッドが使うためにコピーを作る」ときに
「インスタンスの元のホルダーがオブジェクトを破棄」しちゃおかしいだろ。
「別スレッドに渡す」ときにコピーができるもんだろ、ふつー。
819: 736 02/11/15 12:44 AAS
750 :デフォルトの名無しさん :02/11/13 11:21
ひょっとしてrefcountをさらにポインタや参照で管理しようとしてないか?
そんなのrefcountの意味が全くないぞ。根本的にrefcountについて誤解してるだろ。
751 :デフォルトの名無しさん :02/11/13 11:28
>>750
俺もそんな気がして来た。グローバルなオブジェクトや静的なオブジェクトを
参照カウントでやろうとしてるような気もするし。
753 :デフォルトの名無しさん :02/11/13 15:40
分からんヤツやな、、、
refする前にreleaseが発行されてrefcount==0になる
可能性があるなら、refする前に、oobjectが生きてて、
refできるか確かめないかんやろ。その結果、objectが
死んでるなら、refしてobject渡すのは諦めなアカン。
で、そこでobjectが死んでるのが間違いなら、releaseか
refの発行の仕方がオカシイんや。
820: 736 02/11/15 12:45 AAS
767 :デフォルトの名無しさん :02/11/13 21:20
>>736
参照カウントが 1 のオブジェクトを複数のスレッドから参照してる時点で、
ref を呼び忘れてる。
参照回数0 のオブジェクトに到達することが正しい振る舞いだとしたら、
それは通常の参照じゃなく、弱い参照だ。
769 :デフォルトの名無しさん :02/11/13 23:23
> あるスレッドAが参照カウントを持つOのインスタンスをつくって、
COM知ってさえいれば・・・
772 :デフォルトの名無しさん :02/11/13 23:58
なんか皆さん盛り上がってますが…
>>745 >>769に同意。
リファレンスカウントのサンプルを見たければCOMを勉強すればよい。
それと。日本語で一所懸命書かれてもどうにも伝わりにくいようですな。
C言語で(擬似コードでも可)書いた方が意図が伝わると思いますが。
773 :デフォルトの名無しさん :02/11/14 00:03
>>760
> 参照を受け取った時には、当然参照カウントは増えていますが、Oの参照カウントを
> (クリティカルセクション獲得後)増やそうとしたら、スレッドAが解放してしまっていた
> わけです。
そりゃカウントミスってる。AがOを持ってるところでBがOの参照を受け取って
カウントも増やしたんなら、カウントは2以上のはずだ。その状態でAが解放し
てしまうというのはバグ。
822(1): 736 02/11/15 12:51 AAS
君らのしつこさを確認させてやっただけだよ
824: 736 02/11/15 12:58 AAS
結局誰も判らんのか。それならそう言えよ無能者ども。
827(1): 736 02/11/15 13:07 AAS
まだ言ってるのか。
>参照カウントのインクリメントにはロックは*原理的に*必要不可欠。
>してないのはシングルスレッドを前提にしてる場合だけ。
>わかった?
void ref() {
EnterCriticalSection(&m_mutex);
InterlockedIncrement(&m_ref);
LeaveCriticalSection(&m_mutex);
}
void release() {
EnterCriticalSection(&m_mutex);
if (InterlockedDecrement(&m_ref) == 0) {
delete this;
}
LeaveCriticalSection(&m_mutex);
}
としたら満足か?(W
828: 736 02/11/15 13:09 AAS
>826
おまえ、InterlockXXってなんのためにあるのか知らんだろ。
知らない奴に限って、無駄なレスを返しやがる。
831: 736 02/11/15 13:21 AAS
>>836
あのなあ、
>>参照カウントのインクリメントにはロックは*原理的に*必要不可欠。
>>してないのはシングルスレッドを前提にしてる場合だけ。
>>わかった?
というのは読めないのか。お前は、自然言語にたいする理解力は0だな。
ロックかけなきゃだめだと言ってるやつがいるから、ロックしたまで。
なーんの解決にもならんし、もともと、Interlockしてるから不要なんだがな。
832: 736 02/11/15 13:21 AAS
>830
だわ
833: 736 02/11/15 13:23 AAS
で?826も逃げたのか。全く都合が悪くなると逃げて…自分の発言に席にもてよ。
どうせ、別人のフリしてまた別の事言い出すんだろうが
834: 736 02/11/15 13:26 AAS
ん?deleteまではロックしなきゃダメかな。
まあ、どのみちref()でロック獲得したときに、解放済みというのは避けられんが。
836(1): 736 02/11/15 13:34 AAS
やっぱり、List::get()でリストの検索処理が丸ごとロックするしかないのか。
838(1): 736 02/11/15 13:49 AAS
それ以外に無いのか聞いてんだが。
ここのいる連中じゃ無理のようだ(W
839(1): 736 02/11/15 13:53 AAS
>812
>「どこにでもある」 が 「おかしくない」 の理由には全然ならない事に気付け。
>つーか、そんなのそうそう転がってないはずなんだが、あんたよっぽどクソな
>サンプルに見舞われてるんだな。
812も逃げたようだな。逃げ足の速い連中だ。
845: 736 02/11/15 15:06 AAS
>840
またバカが湧いてきた。
>散々いわれてんのに。>>762とか>>785とか。
>762は、各オブジェクト毎にロック掛けるって意味ならロックが多量に必要だし、リストにはロック掛けないのか?
リストにロックかけるんだったら、各オブジェクト毎に掛ける必要なし。
君のような厨には理解で菌だろうがな。
>大体間接的に渡すって話自体>>789くらいでいきなりだし。
間接的?ハァ?頭大丈夫?
785は俺だ。
たくっ。ろくに読まないでレスするアホウは書くなっつの。
>いつまでも君の相手してらんないしね。
>漏れもそろそろ出かけなきゃならないんでバイバイ。
いや、君みたいなアホウに相手してくれとは言ってないから(W
お呼びでないの(Wつか出てくんなっての
大体、レスして何か言われたら自分が誰かわかるように名前に番号入れるもんだろ。
言いっぱなしで自己満足してる厨が多すぎ。
846: 736 02/11/15 15:16 AAS
740 :デフォルトの名無しさん :02/11/12 21:24
ref() と release() が互いに排他してなきゃ動くわけないじゃん。
826 :デフォルトの名無しさん :02/11/15 13:03
>>813
> 共有しているオブジェクトの集合に丸ごとロックかけずに、
> 各オブジェクトの参照カウントだけで済むかがポイントなのに、
参照カウントのインクリメントにはロックは*原理的に*必要不可欠。
してないのはシングルスレッドを前提にしてる場合だけ。
わかった?
こういう連中は、
void ref() {
EnterCriticalSection(&m_cs);
++m_ref;
LeaveCriticalSection(&m_cs);
}
void release() {
EnterCriticalSection(&m_cs);
if (--m_ref) == 0) {
delete this;
}
LeaveCriticalSection(&m_cs);
}
って書いてるのかな。馬鹿だなー。
こんな事言ってる奴が多いのは オ ド ロ キ。
もはや都市伝説だな。
847: 736 02/11/15 15:17 AAS
おっ!
830が、慌ててネットで調べ始めた。まあ、自分の馬鹿さ加減を思い知れ。
848: 736 02/11/15 15:21 AAS
おっ!
他にもInterlockだけじゃダメだと思ってる奴も多いな。
まあ、release()のLeaveCriticalSectionがdelete以降なのは論外だが、
void ref() {
InterlockedIncrement(&m_ref);
}
void release() {
if (InterlockedDecrement(&m_ref) == 0) {
delete this;
}
}
じゃだめだと思ってるやつは何か言ってみろ。
どうせ逃げんだろうけどな。
851: 736 02/11/15 15:48 AAS
おいおい、本当にのこのこ出てきたよ。恥ずかしい奴だ。
852: 736 02/11/15 15:50 AAS
>しかし、危険性において 846 のコードは結局 848 と変わらないな。
説明してみろよ。わくわく。
Bのところに行くのは、どういう場合さ?
856: 736 02/11/15 16:03 AAS
あげてねーじゃん
857: 736 02/11/15 16:04 AAS
>855
リストである必要なし。
グローバル変数など共有してれば同じ。
この場合動的じゃなきゃ意味無いが。
861: 736 02/11/15 16:13 AAS
m_csってメンバー変数じゃないのか?
ref()のEnterCriticalSectionでブロックされてるときに
deleteされるのは大丈夫か?
首尾よく、ref()でCriticalSectionに入れてもm_refは不定だぞ。
862: 736 02/11/15 16:16 AAS
で?849はやっぱり逃げたのか。
866: 736 02/11/15 16:30 AAS
>865
と言うと?
>864
おい!あるってぞ。言い返せよ。
873(1): 736 02/11/15 17:18 AAS
それは、16スレッドが同時に書き込めるのか?
各スレッドが別の要素にアクセスするとして。
リストが要素数なんか持ってても大丈夫?
単純なリストならまだしも、空リストとか管理されてると結局その中の
一つのスレッドしか書き込みできない(というか排他制御が必要な)気がするが。
881(1): 736 02/11/15 21:01 AAS
お前ら無能すぎ。そんな程度で2ちゃん来てんじゃねーよ。
885: 736 02/11/15 21:13 AAS
>>881
とうとう偽者まで出てきたか。
886(1): 736 02/11/15 21:13 AAS
適当ほざいてんじゃねーよ
帰って寝てろ
ワラワラ
887: 736 02/11/15 21:16 AAS
881=882だろ。
>880
> 第三に、参照カウントも複数のスレッドから
> 参照されるから、これも排他しなくちゃならないよね。
どういう風に?(W
888: 736 02/11/15 21:17 AAS
>886
おまえも881だろ。
>884=870
もうちょっと、説明してくれや。
889: 736 02/11/15 21:18 AAS
騙ってまで何がやりたいんだか
>880
教科書のコピペはやめようね
899: 736 02/11/15 22:02 AAS
>898
ギブアップしたの?(W
926: 02/11/16 07:53 AAS
なんでこんなくだらん事で話を引っ張ってるの? > >>736
上下前次1-新書関写板覧索設栞歴
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル
ぬこの手 ぬこTOP 0.042s