スレッドは、参照カウンターの使用を理解することとは無関係だと思います。ポイントはむしろ所有権と存続期間であり、スレッドはこれによって影響を受けるものの 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 回呼び出された場合でも (再帰を考えてください!)、関数への各呼び出しのローカル変数は異なります。また、変数名は人間が読むためのものです。コンパイラはこれらを完全に排除します。