[インデックス 11156] ファイルの概要
このコミットは、Go言語の仕様書 (doc/go_spec.html
) における select
ステートメントの動作に関する記述を修正するものです。具体的には、複数の case
が実行可能な場合にどの case
が選択されるかについての表現が、「pseudo-random fair (擬似ランダムで公平な)」から「uniform pseudo-random (一様擬似ランダムな)」に変更されています。
コミット
commit 5f7337769c4a09c34d32ca29ffdeb5c5c19aca41
Author: Rob Pike <r@golang.org>
Date: Fri Jan 13 13:38:36 2012 -0800
spec: change the wording regarding select statement choice
s/pseudo-random fair/uniform pseudo-random/
This careful word choice soothes the theoretically inclined.
R=golang-dev, rsc, gri
CC=golang-dev
https://golang.org/cl/5528098
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5f7337769c4a09c34d32ca29ffdeb5c5c19aca41
元コミット内容
spec: change the wording regarding select statement choice
s/pseudo-random fair/uniform pseudo-random/
This careful word choice soothes the theoretically inclined.
R=golang-dev, rsc, gri
CC=golang-dev
https://golang.org/cl/5528098
変更の背景
この変更の背景には、Go言語の select
ステートメントの動作、特に複数の通信操作が同時に準備完了になった場合の選択メカニズムに関する、より厳密で正確な記述を求める要求がありました。元の「pseudo-random fair (擬似ランダムで公平な)」という表現は、その意味合いが曖昧であり、理論的な厳密さを求める人々("theoretically inclined")にとっては不十分であると認識されていました。
「公平性 (fairness)」という言葉は、並行プログラミングにおいて様々な解釈が可能であり、例えば「最終的に全ての選択肢が選ばれる機会を持つ」といった弱い公平性から、「全ての選択肢が等しい確率で選ばれる」といった強い公平性まで幅があります。Go言語の select
ステートメントの実装は、複数の case
が準備完了になった場合、それらの case
の中から一様分布に従って擬似乱数的に一つを選択します。この挙動を正確に反映するため、「uniform pseudo-random (一様擬似ランダムな)」という表現が採用されました。これにより、仕様の記述が実装の振る舞いと完全に一致し、誤解の余地がなくなります。
前提知識の解説
Go言語の select
ステートメント
Go言語の select
ステートメントは、複数のチャネル操作(送受信)を同時に待機し、そのうちの一つが準備完了になったときにその操作を実行するための強力な並行処理プリミティブです。select
は、他の言語における switch
ステートメントに似ていますが、評価されるのはチャネルの通信操作です。
基本的な構文は以下の通りです。
select {
case <-ch1:
// ch1 から値を受信
case ch2 <- value:
// ch2 へ値を送信
case <-time.After(timeout):
// タイムアウト
default:
// どのチャネルも準備完了でない場合(オプション)
}
select
ステートメントの重要な特性は以下の通りです。
- ブロッキング:
default
ケースがない場合、select
はどれかのcase
が準備完了になるまでブロックします。 - 非ブロッキング:
default
ケースがある場合、どのcase
も準備完了でなければdefault
ケースが即座に実行され、select
はブロックしません。 - 複数の
case
が準備完了の場合: ここが今回のコミットの焦点です。複数のcase
が同時に通信可能になった場合、select
はそれらの準備完了なcase
の中から一つをランダムに選択して実行します。
擬似乱数 (Pseudo-random) と一様擬似乱数 (Uniform Pseudo-random)
- 擬似乱数 (Pseudo-random): コンピュータで生成される乱数は、実際には完全にランダムではありません。ある初期値(シード)から決定論的なアルゴリズムによって生成されるため、「擬似乱数」と呼ばれます。しかし、統計的にはランダムな特性(例えば、均等な分布)を示すように設計されています。
- 一様擬似乱数 (Uniform Pseudo-random): これは、生成される乱数が特定の範囲内で一様分布に従うことを意味します。つまり、その範囲内のどの値も等しい確率で出現するということです。
select
ステートメントの文脈では、複数の準備完了なcase
がある場合、それら全てのcase
が等しい確率で選択されることを保証します。
公平性 (Fairness)
並行処理における公平性とは、リソースや実行機会が複数の競合するエンティティ(この場合は select
の case
)にどのように分配されるかという概念です。
- 弱い公平性 (Weak Fairness): ある操作が最終的に実行される機会を持つことを保証します。例えば、ある
case
が常に準備完了であるならば、いつかはそれが選択される、といった保証です。 - 強い公平性 (Strong Fairness): ある操作が継続的に準備完了であるならば、最終的にそれが選択されることを保証します。
- 確率的公平性 (Probabilistic Fairness): 各操作が選択される確率がゼロではないことを保証します。
Goの select
における「uniform pseudo-random」は、より強い確率的公平性、すなわち「等しい確率」での選択を保証するものです。
技術的詳細
この変更は、Go言語の select
ステートメントの動作に関する仕様の記述を、より正確で曖牲のないものにするためのものです。
元の記述:
If multiple cases can proceed, a pseudo-random fair choice is made to decide which single communication will execute.
(複数のケースが進行可能な場合、擬似ランダムで公平な選択が行われ、どの単一の通信が実行されるかが決定される。)
変更後の記述:
If multiple cases can proceed, a uniform pseudo-random choice is made to decide which single communication will execute.
(複数のケースが進行可能な場合、一様擬似ランダムな選択が行われ、どの単一の通信が実行されるかが決定される。)
この変更の技術的な重要性は以下の点にあります。
- 曖昧さの排除: 「fair (公平な)」という言葉は、並行処理の文脈で様々な解釈が可能です。例えば、単に「飢餓状態にならない」という意味での公平性(最終的には選ばれる)と、「等しい確率で選ばれる」という意味での公平性では、プログラムの挙動に対する期待が大きく異なります。「uniform (一様)」という修飾語を追加することで、選択が統計的に均等な確率分布に従うことが明確になります。これは、並行プログラムの予測可能性と信頼性を高める上で非常に重要です。
- 実装との整合性: Goのランタイムにおける
select
の実装は、実際に準備完了なcase
の中から一様分布に従ってランダムに選択を行います。この仕様変更は、言語仕様が実際のランタイムの挙動を正確に反映するようにするためのものです。仕様と実装の間に乖離があると、開発者は混乱し、予期せぬバグにつながる可能性があります。 - 理論的な厳密さ: 言語仕様は、その言語の動作を定義する最も権威ある文書です。特に並行処理のような複雑な領域では、厳密で正確な言葉遣いが求められます。「theoretically inclined (理論的な傾向のある人々)」というコミットメッセージの記述は、この変更が形式的な検証や理論的な分析を行う人々にとって、より受け入れやすいものとなることを示唆しています。一様分布は統計学的に明確な概念であり、その導入は仕様の厳密性を向上させます。
- デッドロックやライブロックの回避:
select
ステートメントが公平な選択を行うことは、特定のcase
が永遠に選択されない「飢餓状態 (starvation)」や、プログラムが進行しない「ライブロック (livelock)」を防ぐ上で重要です。一様擬似乱数による選択は、全ての準備完了なcase
に等しい機会を与えることで、これらの問題を効果的に回避します。
この変更は、Go言語の設計哲学である「シンプルさ」と「実用性」を保ちつつも、その基盤となる並行処理モデルの厳密性と正確性を追求する姿勢を示しています。
コアとなるコードの変更箇所
変更は doc/go_spec.html
ファイル内で行われています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of January 9, 2012 -->
+<!-- subtitle Version of January 13, 2012 -->
<!--
TODO
@@ -4240,7 +4240,7 @@ effects in that evaluation will occur for all the communications
in the "select" statement.
</p>
<p>
-If multiple cases can proceed, a pseudo-random fair choice is made to decide
+If multiple cases can proceed, a uniform pseudo-random choice is made to decide
which single communication will execute.
<p>
The receive case may declare one or two new variables using a
コアとなるコードの解説
このコミットにおける主要なコード変更は、Go言語の仕様書 (doc/go_spec.html
) の以下の行にあります。
-If multiple cases can proceed, a pseudo-random fair choice is made to decide
+If multiple cases can proceed, a uniform pseudo-random choice is made to decide
この変更は、select
ステートメントの動作に関する記述を更新するものです。
-
で始まる行: 変更前の記述です。「pseudo-random fair
(擬似ランダムで公平な)」という表現が使われています。+
で始まる行: 変更後の記述です。「uniform pseudo-random
(一様擬似ランダムな)」という表現に変更されています。
この一単語の変更は、Go言語の select
ステートメントが複数のチャネル操作が同時に準備完了になった場合に、どの操作を選択するかというメカニズムの厳密な定義を確立します。
「pseudo-random fair
」という表現は、公平性という概念が曖昧であるため、実装の詳細や期待される振る舞いについて誤解を招く可能性がありました。例えば、「公平」が「最終的に全てのケースが選ばれる機会を持つ」という意味なのか、「全てのケースが等しい確率で選ばれる」という意味なのかが不明瞭でした。
「uniform pseudo-random
」という表現は、この曖昧さを解消します。これは、準備完了な全ての case
が等しい確率で選択されることを明確に示しています。この「一様 (uniform)」という言葉が、統計的な分布の均等性を保証し、Goのランタイムが実際にそのように動作することを仕様として明記しています。
また、このコミットでは、仕様書のバージョン日付も更新されています。
-<!-- subtitle Version of January 9, 2012 -->
+<!-- subtitle Version of January 13, 2012 -->
これは、仕様書がこの変更を含む形で更新されたことを示しています。
関連リンク
- Go Gerrit Change: https://golang.org/cl/5528098
参考にした情報源リンク
- The Go Programming Language Specification - Select statements: https://go.dev/ref/spec#Select_statements
- Go Concurrency Patterns: Select (Go Blog): https://go.dev/blog/go-concurrency-patterns-select
- Go's select statement is not fair (Stack Overflow discussion): https://stackoverflow.com/questions/10952000/gos-select-statement-is-not-fair (この議論は、Goの
select
の公平性に関する一般的な誤解と、それが「一様擬似乱数」であることを理解する上で役立ちます。) - Go issue 11562: runtime: select should be fair (or at least not unfair): https://github.com/golang/go/issues/11562 (このissueは、
select
の公平性に関する議論の背景を提供します。ただし、このコミット自体はissue 11562よりも前のものです。) - Wikipedia - Pseudorandom number generator: https://en.wikipedia.org/wiki/Pseudorandom_number_generator
- Wikipedia - Uniform distribution (discrete): https://en.wikipedia.org/wiki/Uniform_distribution_(discrete)
- Wikipedia - Fairness (computer science): https://en.wikipedia.org/wiki/Fairness_(computer_science)