Documentation
¶
Overview ¶
パッケージsyncは相互排他ロックなどの基本的な同期プリミティブを提供します。OnceとWaitGroup以外の型は、低レベルのライブラリルーチンでの使用を意図しています。より高レベルな同期はチャネルと通信を介して行う方が良いです。
このパッケージで定義された型を含む値は、コピーしないでください。
Index ¶
- func OnceFunc(f func()) func()
- func OnceValue[T any](f func() T) func() T
- func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2)
- type Cond
- type Locker
- type Map
- func (m *Map) CompareAndDelete(key, old any) (deleted bool)
- func (m *Map) CompareAndSwap(key, old, new any) bool
- func (m *Map) Delete(key any)
- func (m *Map) Load(key any) (value any, ok bool)
- func (m *Map) LoadAndDelete(key any) (value any, loaded bool)
- func (m *Map) LoadOrStore(key, value any) (actual any, loaded bool)
- func (m *Map) Range(f func(key, value any) bool)
- func (m *Map) Store(key, value any)
- func (m *Map) Swap(key, value any) (previous any, loaded bool)
- type Mutex
- type Once
- type Pool
- type RWMutex
- type WaitGroup
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func OnceFunc ¶ added in v1.21.0
func OnceFunc(f func()) func()
OnceFuncは関数fを一度だけ呼び出す関数を返します。返された関数は並行して呼び出すことができます。
fがパニックを起こした場合、返された関数はすべての呼び出しで同じ値でパニックを起こします。
func OnceValue ¶ added in v1.21.0
func OnceValue[T any](f func() T) func() T
OnceValue は、関数 f を一度だけ呼び出し、f の戻り値を返す関数を返します。 返された関数は、同時に呼び出すことができます。
f がパニックを起こした場合、返された関数はすべての呼び出しで同じ値を持つパニックを発生させます。
func OnceValues ¶ added in v1.21.0
func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2)
OnceValuesは、fを一度だけ呼び出し、fによって返された値を返す関数を返します。返された関数は並行して呼び出すことができます。
fがパニックを引き起こした場合、返された関数はすべての呼び出しで同じ値でパニックを起こします。
Types ¶
type Cond ¶
type Cond struct { // 条件を観察または変更する間は、Lを保持します L Locker // contains filtered or unexported fields }
Condはイベントの発生を待つまたは宣言するための待機ポイントである条件変数を実装します。
各Condには関連付けられたLocker L(通常は*Mutexまたは*RWMutex)があり、条件を変更するときやWaitメソッドを呼び出すときに保持する必要があります。
最初の使用後にCondをコピーしてはいけません。
Goメモリモデルの用語では、CondはBroadcastまたはSignalの呼び出しはそれがアンブロックする任意のWait呼び出しよりも「前に同期する」と整理されています。
単純な使用例では、ユーザーはチャネルを使用する方がCondよりも優れています(Broadcastはチャネルを閉じることに対応し、Signalはチャネルに送信することに対応します)。
sync.Condの代わりに他のものについては、Roberto Clapisさんの高度な並行性パターンシリーズとBryan Millsさんの並行性パターンに関するトークを参照してください。
func (*Cond) Broadcast ¶
func (c *Cond) Broadcast()
Broadcastは、cで待機しているすべてのゴルーチンを起こします。
呼び出し元がc.Lを保持していることは許可されていますが、必須ではありません。
func (*Cond) Signal ¶
func (c *Cond) Signal()
cに待機しているゴルーチンがあれば、Signalは1つのゴルーチンを起こします。
呼び出し元がc.Lを保持していることは必須ではありませんが、許可されています。
Signal()はゴルーチンのスケジューリングの優先順位に影響を与えません。他のゴルーチンがc.Lをロックしようとしている場合、"待機中"のゴルーチンよりも先に起きる場合があります。
func (*Cond) Wait ¶
func (c *Cond) Wait()
Waitはc.Lのロックを解除して、呼び出し元のゴルーチンの実行を一時停止します。 後で再開すると、Waitは戻る前にc.Lをロックします。他のシステムとは異なり、 WaitはBroadcastまたはSignalによって起こされない限り戻りません。
Waitが待機している間、c.Lはロックされていないため、呼び出し元は 待機が返るときに条件が真であることを前提とすることはできません。代わりに、 呼び出し元はループ内でWaitを使用する必要があります:
c.L.Lock() for !condition() { c.Wait() } ... 条件を活用する ... c.L.Unlock()
type Map ¶ added in v1.9.0
type Map struct {
// contains filtered or unexported fields
}
MapはGoのmap[interface{}]interface{}に似ていますが、追加のロックや調整なしで複数のゴルーチンによる並行使用が安全です。 ロード、ストア、および削除は均等化された一定の時間で実行されます。
Map型は特殊化されています。ほとんどのコードでは代わりに単純なGoのmapを使用すべきであり、 型の安全性を向上させ、他の不変条件とマップのコンテンツを維持しやすくするために別個のロックや調整を行うべきです。
Map型は2つの一般的な使用例に最適化されています:(1)特定のキーのエントリが一度しか書き込まれずに多くの回数読み取られる場合、 つまり成長のみのキャッシュ、または(2)複数のゴルーチンが交差しないキーのセットの読み取り、書き込み、上書きを行う場合。 これらの2つの場合において、Mapの使用は、別個のMutexやRWMutexとペアになったGoのマップと比較して、 ロックの競合を大幅に減らすことができます。
ゼロ値のMapは空で使用準備ができています。Mapは最初の使用後にコピーされてはなりません。
Goメモリモデルの用語では、Mapは書き込み操作が行われたときにそれに続く読み取り操作を "書き込みより前に同期します"。 ここで、読み取りと書き込み操作は以下のように定義されます。 Load、LoadAndDelete、LoadOrStore、Swap、CompareAndSwap、CompareAndDeleteは読み取り操作です。 Delete、LoadAndDelete、Store、Swapは書き込み操作です。 LoadOrStoreは、loadedがfalseで返された場合に書き込み操作です。 CompareAndSwapは、swappedがtrueで返された場合に書き込み操作です。 CompareAndDeleteは、deletedがtrueで返された場合に書き込み操作です。
func (*Map) CompareAndDelete ¶ added in v1.20.0
CompareAndDeleteは、keyの値がoldと等しい場合、そのエントリを削除します。 oldの値は比較可能な型である必要があります。
マップにkeyの現在の値がない場合、CompareAndDeleteはfalseを返します(oldの値がnilインターフェース値であっても)。
func (*Map) CompareAndSwap ¶ added in v1.20.0
CompareAndSwapは、キーの古い値と新しい値を交換します。 マップに格納されている値が古い値と等しい場合にのみ行われます。 古い値は比較可能な型でなければなりません。
func (*Map) Load ¶ added in v1.9.0
Loadは、キーに対応するマップ内の値を返します。もし値が存在しない場合はnilを返します。 okの結果は、値がマップ内で見つかったかどうかを示します。
func (*Map) LoadAndDelete ¶ added in v1.15.0
LoadAndDelete はキーに対応する値を削除し、もし値が存在する場合は以前の値を返します。 読み込まれた結果はキーが存在するかどうかを報告します。
func (*Map) LoadOrStore ¶ added in v1.9.0
LoadOrStore は、キーが存在する場合は既存の値を返します。 それ以外の場合は、指定された値を格納して返します。 読み込まれた結果が true の場合、値は読み込まれ、false の場合は格納されました。
func (*Map) Range ¶ added in v1.9.0
Rangeはマップ内の各キーと値に対して順番にfを呼び出します。 もしfがfalseを返す場合、Rangeは繰り返しを停止します。
RangeはMapの内容に一貫したスナップショットに必ずしも対応していません: 各キーは複数回訪れませんが、任意のキーの値が同時に格納または削除される場合(fによっても含まれます)、 RangeはRange呼び出し中の任意の時点からのそのキーのマッピングを反映することがあります。 Rangeはレシーバー上の他のメソッドをブロックしません。f自体もmの任意のメソッドを呼び出すことができます。
fが一定回数の呼び出し後にfalseを返す場合でも、Rangeはマップ内の要素数の数に比例するO(N)の可能性があります。
type Mutex ¶
type Mutex struct {
// contains filtered or unexported fields
}
Mutexは相互排他ロックです。 Mutexのゼロ値はロックされていないMutexです。
Mutexは最初の使用後にコピーしてはいけません。
Goのメモリモデルの用語では、Unlockのn回目の呼び出しはm回目のLockの前に同期されます(n < m)。 TryLockの成功した呼び出しはLockの呼び出しと同等です。 TryLockの失敗した呼び出しはどのような「同期前の」関係も確立しません。
func (*Mutex) Lock ¶
func (m *Mutex) Lock()
Lock は m をロックします。 もし既にロックが使用中である場合、呼び出し元のゴルーチンは ミューテックスが利用可能になるまでブロックされます。
type Once ¶
type Once struct {
// contains filtered or unexported fields
}
Onceは正確に1つのアクションを実行するオブジェクトです。
Onceは最初の使用後にコピーしてはいけません。
Goメモリモデルの用語では、fからの戻り値はonce.Do(f)の呼び出しの戻り値よりも前に同期します。
Example ¶
package main import ( "github.com/shogo82148/std/fmt" "github.com/shogo82148/std/sync" ) func main() { var once sync.Once onceBody := func() { fmt.Println("Only once") } done := make(chan bool) for i := 0; i < 10; i++ { go func() { once.Do(onceBody) done <- true }() } for i := 0; i < 10; i++ { <-done } }
Output: Only once
func (*Once) Do ¶
func (o *Once) Do(f func())
Doは、Onceのインスタンスで最初にDoが呼び出された場合のみ、関数fを呼び出します。つまり、次のように与えられた場合、
var once Once
もしこのように複数回once.Do(f)が呼び出された場合、最初の呼び出しのみがfを実行し、 それぞれの呼び出しでfが異なる値を持っていても、その値に関係なく実行されます。各関数の実行には新しいOnceのインスタンスが必要です。
Doは、一度だけ実行する必要のある初期化に使用されます。fは引数なしの関数ですので、Doによって呼び出される関数の引数を捕捉するために関数リテラルを使用する必要があるかもしれません:
config.once.Do(func() { config.init(filename) })
Doへの呼び出しがfの返り値が返されるまで戻らないため、fがDoの呼び出しを引き起こすとデッドロックが発生します。
fがパニックした場合、Doはそれを戻ったとみなします。その後のDoの呼び出しはfを呼び出さずに返ります。
type Pool ¶ added in v1.3.0
type Pool struct { // Newは、Getがnilを返す場合に値を生成するための関数を指定するオプションです。 // Getの呼び出しと同時に変更することはできません。 New func() any // contains filtered or unexported fields }
プールとは個別に保存および取り出しが可能な一時オブジェクトのセットです。
プールに保存されたアイテムは、通知なしにいつでも自動的に削除される可能性があります。 これが発生する際にプールが唯一の参照を保持している場合、そのアイテムは解放される可能性があります。
プールは、複数のゴルーチンによる同時の使用に対して安全です。
プールの目的は、割り当てされたが未使用のアイテムをキャッシュして後で再利用することで、 ガベージコレクタにかかる負荷を軽減することです。つまり、効率的かつスレッドセーフな無料リストを構築することを簡単にします。 ただし、プールはすべての無料リストに適しているわけではありません。
プールの適切な使用例は、パッケージの独立した並行クライアント間で静に共有され、 潜在的に再利用される一時アイテムのグループを管理することです。 プールは、多くのクライアント間で割り当てのオーバーヘッドを分散する方法を提供します。
プールの良い使用例は、fmtパッケージにあります。これは一時的な出力バッファのサイズを動的に管理しています。 このストアは、負荷がかかった場合(多くのゴルーチンがアクティブに印刷している場合)に拡大し、静かな場合には縮小します。
一方、短命なオブジェクトの一部として維持される無料リストは、プールには適していません。 なぜなら、このシナリオではオーバーヘッドを適切に分散させることができないからです。 このようなオブジェクトは、独自の無料リストを実装する方が効率的です。
プールは、最初の使用後にコピーしないでください。
Goのメモリモデルの用語では、Put(x)の呼び出しは同じ値xを返すGet呼び出しよりも「前に同期します」。 同様に、Newがxを返す「前に同期します」Get呼び出しが同じ値xを返します。
Example ¶
Log(os.Stdout, "path", "/search?q=flowers")
Output: 2006-01-02T15:04:05Z path=/search?q=flowers
type RWMutex ¶
type RWMutex struct {
// contains filtered or unexported fields
}
RWMutexは、読み込み/書き込み相互排他的なロックです。 ロックは任意の数の読み込み者または単一の書き込み者によって保持することができます。 RWMutexのゼロ値はロックされていないミューテックスです。
RWMutexは、最初の使用後にコピーしてはいけません。
ゴルーチンが読み込みのためにRWMutexを保持しており、他のゴルーチンが Lockを呼び出す可能性がある場合、初期の読み込みロックが解放されるまで、 他のゴルーチンは読み込みロックを獲得できることは期待できません。 特に、再帰的な読み込みロックは禁止されています。これは、ロックが最終的に利用可能になるようにするためです。 ブロックされたLock呼び出しは、新しい読み込み者がロックを獲得するのを排除します。
Goのメモリモデルの用語では、Unlockのn回目の呼び出しは、 任意のn < mに対して、m回目のLockの呼び出しの前に同期化します(Mutexと同様)。 また、RLockの呼び出しに対して、n回目のUnlockの呼び出しがあるために n+1回目のLockの呼び出しの前に同期化されます。
func (*RWMutex) Lock ¶
func (rw *RWMutex) Lock()
Lockはrwを書き込み用にロックします。 もし既に読み込みや書き込みのためにロックされている場合、 Lockは利用可能になるまでブロックします。
func (*RWMutex) RLock ¶
func (rw *RWMutex) RLock()
RLockはrwの読み取りのためにロックします。
再帰的な読み取りのために使用すべきではありません。ブロックされたLock呼び出しは、 新しい読み取り者がロックを取得することを排除します。RWMutex型のドキュメントを参照してください。
func (*RWMutex) RLocker ¶
RLockerはLockerインターフェースを返します。このインターフェースは、rw.RLockとrw.RUnlockを呼び出してLockとUnlockメソッドを実装します。
func (*RWMutex) RUnlock ¶
func (rw *RWMutex) RUnlock()
RUnlockは1回のRLock呼び出しを元に戻します。 他の同時読み取りプロセスには影響しません。 RUnlockが呼び出される時にrwが読み取りロックされていない場合、ランタイムエラーが発生します。
func (*RWMutex) TryLock ¶ added in v1.18.0
TryLockは、rwを書き込み用にロックしようとし、成功したかどうかを報告します。
TryLockの正しい使用法は存在しますが、それらはまれであり、 mutexの特定の使用法におけるより深刻な問題の兆候であることが多いため、 TryLockの使用は避けるべきです。
type WaitGroup ¶
type WaitGroup struct {
// contains filtered or unexported fields
}
WaitGroupは、一連のゴルーチンの完了を待機します。 メインゴルーチンは、待機するゴルーチンの数を設定するためにAddを呼び出します。 それぞれのゴルーチンは実行され、終了時にDoneを呼び出します。 同時に、全てのゴルーチンが終了するまでブロックするためにWaitを使用できます。
WaitGroupは、初回使用後にコピーしてはいけません。
Goのメモリモデルの用語である、Doneへの呼び出しは、それによってブロックが解除される任意のWait呼び出しの前に「同期します」。
Example ¶
この例では、複数のURLを同時にフェッチし、WaitGroupを使用して、すべてのフェッチが完了するまでブロックします。
var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.example.com/", } for _, url := range urls { // WaitGroup のカウンターをインクリメントする。 wg.Add(1) // URLを取得するために、ゴルーチンを起動します。 go func(url string) { // ゴルーチンが完了したら、カウンタを減らす。 defer wg.Done() // URLを取得する。 http.Get(url) }(url) } // すべてのHTTPフェッチが完了するまで待ちます。 wg.Wait()
Output:
func (*WaitGroup) Add ¶
AddはWaitGroupのカウンターにデルタを追加します。デルタは負であることもあります。 カウンターがゼロになると、Waitでブロックされているすべてのゴルーチンが解放されます。 カウンターが負になると、Addはパニックを発生させます。
カウンターがゼロの状態で正のデルタで呼び出される場合は、Waitより前に実行される必要があることに注意してください。 負のデルタで呼び出される場合や、カウンターがゼロより大きい状態で正のデルタで呼ばれる場合は、任意のタイミングで発生する場合があります。 通常、これはAddの呼び出しは、ゴルーチンの作成または待機する他のイベントの直前に実行されるべきことを意味します。 WaitGroupが複数の独立したイベントセットを待機するために再利用される場合、新しいAdd呼び出しは以前のすべてのWait呼び出しが返された後に行われる必要があります。 WaitGroupの例を参照してください。