2

私はglibで遊んでいます。

  1. 参照カウントを使用してオブジェクトのメモリを管理します。
  2. 複数のスレッドをサポートします。

私が理解できないのは、彼らがどのように一緒に遊んでいるのかです。すなわち:

  1. 各スレッドではglib、入力で渡されたオブジェクトの参照カウントが増加していないようです(私の知る限り、スレッド共有オブジェクトと呼びます)。本当ですか?(または、適切なコードを見つけることができませんでしたか?) メイン スレッド (それらを参照カウントする責任がある) 以外に、それらを共有する各スレッドのスレッド共有オブジェクトへの参照カウントを増やさないのは一般的な方法ですか?
  2. それでも、各スレッドは、それ自体で動的に作成されたオブジェクトの参照カウントを増やします。プログラマは、名前の衝突やメモリ リークを防ぐために、各スレッドで変数に同じ名前を付けないようにする必要がありますか? (たとえば、私の写真では、thread2 は output_object と呼ばれるヒープ変数を作成しないでください。そうしないと、同じ名前のスレッド 1 のヒープ変数と衝突します)?

更新: (質問 2) への回答はノーです。これらの変数の可視性スコープが交差しないためです: 動的に割り当てられたメモリ (ヒープ) であるか、関数に対してローカルであるか、またはスレッド内のすべての関数がポインターを渡さなくてもそれにアクセスできます引数として

私の質問の実例:

ここに画像の説明を入力

4

2 に答える 2

2

スレッドは、参照カウンターの使用を理解することとは無関係だと思います。ポイントはむしろ所有権と存続期間であり、スレッドはこれによって影響を受けるものの 1 つにすぎません。これは説明するのが少し難しいので、例を使ってわかりやすく説明したいと思います。

次に、main() がオブジェクトを作成し、そのオブジェクトを使用して 2 つのスレッドを開始する例を見てみましょう。問題は、作成されたオブジェクトを誰が所有するかです。簡単な答えは、main() と両方のスレッドがこのオブジェクトを共有するため、所有権が共有されるということです。これをモデル化するには、pthread_create() を呼び出すたびに refcounter をインクリメントする必要があります。呼び出しが失敗した場合は、再度デクリメントする必要があります。それ以外の場合は、オブジェクトの処理が完了したときに、開始されたスレッドがそれを行う必要があります。次に、main() が終了すると、所有権も解放する必要があります。つまり、refcounter をデクリメントします。一般的なルールは、所有者を追加するときに、refcounter をインクリメントすることです。所有者がオブジェクトの処理を完了すると、refcounter がデクリメントされ、最後の 1 つはそれでオブジェクトを破棄します。

では、なぜコードはこれを行わないのでしょうか? まず、最初のスレッドを所有者として追加してから、main() の所有権を 2 番目のスレッドに渡すことで問題を解決できます。これにより、インクリメント/デクリメント操作が 1 回節約されます。しかし、これはまだ起こっていることではありません。代わりに、参照カウントはまったく行われません。単純な理由は、それが使用されていないことです。refcounting のポイントは、ピアである異なる所有者間で動的に割り当てられたオブジェクトの有効期間を調整することです。ここでは、オブジェクトは main() によって作成および所有されますが、2 つのスレッドはピアではなく、メインのスレーブです。main() はスレッドの開始/停止を制御するマスターであるため、オブジェクトの存続期間をそれらと調整する必要はありません。

最後に、それはあなたのコードの例のせいかもしれませんが、main は単純に参照をリークし、OS のクリーンアップに依存していると思います。これは美しくありませんが、害はありません。一般に、オブジェクトを一度割り当てれば、場合によっては参照カウントなしでそれらを永久に使用できます。この例は、アプリケーションのメイン ウィンドウです。これは、ランタイム全体で 1 回だけ必要です。ただし、そのようなオブジェクトを繰り返し割り当てるべきではありません。時間の経過とともに増加する重大なメモリ リークが発生するためです。どちらの場合も、valgrind などのツールによって検出されます。

2 番目の質問に関して、予想されるヒープ変数名の競合に関しては、存在しません。関数ローカルの変数名は衝突できません。これは、それらが異なるスレッドによって使用されるためではなく、同じ関数が同じスレッドによって 2 回呼び出された場合でも (再帰を考えてください!)、関数への各呼び出しのローカル変数は異なります。また、変数名は人間が読むためのものです。コンパイラはこれらを完全に排除します。

于 2013-01-31T21:34:47.513 に答える
1

アップデート:

matthias が以下で述べているように、GObject はスレッドセーフではなく、参照カウント関数のみがスレッドセーフです。

元のコンテンツ:

GObject はスレッド セーフであるはずですが、自分でそれを試したことはありません…</p>

于 2013-01-31T10:16:38.567 に答える