変数のスコープを極力狭くする理由
並行プログラミングをしていなくとも、グローバル変数(大域変数)を多用すると、スパゲッティプログラムになりやすく、バグを生む可能性が高くなります。しかし、余分な労力をつぎ込めば、何とか動作できます。一方、並行プログラミングの場合、正常に動作させる事自体が困難になります。その理由は、処理結果が予想できなくなり、それを防ぐために同期処理を使用すると、デッドロックや優先順位逆転問題などが発生する可能性があるからです。つまり、スコープが広い変数を使う事のコストとリスクが高すぎるのです。
その理由から、理想的には変数は局所的(ローカル)であるべきです。ローカル変数を使用すると、始めから値の不整合が起こりません。それ故、同期処理の必要もなくなります。では、何故その様な事が起こるかというと、ローカル変数をアセンブラレベルで考えれば分かります。
順を追って説明します。グローバル変数は、プロセスごとに決められたメモリアドレスの範囲に配置されますので、同じプロセスに属する個々のスレッドがアクセスできます。一方ローカル変数は、スレッドごとに持つスタック内に保持するので、他のスレッドの影響を受けません。
スレッドがスタックを持つ理由は、各スレッドは通常異なる手続きを呼び出し、異なる実行履歴を持つからです。関数呼び出しを実現するには、呼び出し前にいた場所(アドレス)と引数の値をスタックという形で保持しなくてはなりません。また、ローカル変数の値もスレッドごとに違いますので、スタックに保存しなくてはなりません。もし各スレッドがスタックを持たなければ、必要な情報をレジスタに保存する必要がありますが、レジスタの数は限られていますので、非常に少ない数のスレッドしか実行出来ず、ローカル変数の数も制限される事になります。それでは不都合が多すぎるので、スレッドごとのスタックに保存される形で実現されています。
ローカル変数が使用できない場合は、スレッドローカルストレージ(TLS)を使用します。スレッドが持つスタック内の、決められた場所に変数を保存する事により、他のスレッドの干渉を防ぐ事が出来ます。この変数の名前は定められておらず、プライベート大域変数、TLS内に保持された変数・・・等と、文脈に沿って表現されています。