...

パッケージ sync

概要 ▾

sync パッケージは,排他ロックのような基本的な同期要素を提供します。 Once や WaitGroup 関連を除き,低レベルライブラリルーチンで使用することを意図しています。 高レベル同期には,チャンネルと通信を使ってください。

このパッケージで定義されている型を含む値はコピーしないでください。

type Cond

Cond は条件変数を実装します。 これは,イベントの発生を待っているか,またはその発生をアナウンスしているゴルーチンのランデブーポイントです。

各 Cond には,関連するロッカー L (通常は *Mutex または *RWMutex) があります。 これらは,条件を変更するとき,および Wait メソッドを呼び出すときに保持する必要があります。

最初の使用後に Cond をコピーしてはいけません。

type Cond struct {

    // 状態を取得または変更しながら L を保持
    L Locker
    // エクスポートされていないフィールドがあります
}

func NewCond

func NewCond(l Locker) *Cond

NewCond はロッカー l を持つ新しい Cond を返します。

func (*Cond) Broadcast

func (c *Cond) Broadcast()

ブロードキャストは c を待っているすべての goroutine を起こします。

呼び出し中に発信側が c.L を保持することは許可されていますが必須ではありません。

func (*Cond) Signal

func (c *Cond) Signal()

Signal は,もしあれば, 1 つの goroutine を c で待機させます。

呼び出し中に発信側が c.L を保持することは許可されていますが必須ではありません。

func (*Cond) Wait

func (c *Cond) Wait()

自動的に c.L のロックを解除し,呼び出し側のゴルーチンの実行を中断します。 後で実行を再開した後, Wait は c.L をロックしてから戻ります。 他のシステムとは異なり, Wait は Broadcast または Signal によって起こされない限り戻ることができません。

Wait が最初に再開したときに c.L はロックされていないため,呼び出し元は通常, Wait が戻ったときに条件が真であると見なすことはできません。 代わりに,呼び出し側はループを待つ必要があります。

c.L.Lock()
for !condition() {
    c.Wait()
}
... 条件を利用する ...
c.L.Unlock()

type Locker

Locker は,ロックおよびロック解除できるオブジェクトを表します。

type Locker interface {
    Lock()
    Unlock()
}

type Map 1.9

Map は Go map[interface{}]interface{} のようなものですが,追加のロックや調整なしに複数の goroutines が平行に使用しても安全です。 ロード,ストア,および削除は,一定の償却期間で実行されます。

マップ型は特殊です。 ほとんどのコードでは,型安全性を高め,マップの内容と共に他の不変式を簡単に管理できるようにするために,代わりにプレーンな Go マップを使用してください。

Map 型は 2 つの一般的なユースケースのために最適化されています : (1) 与えられたキーのエントリが一度だけ書かれて何度も読まれるキャッシュのように何度も読まれる場合,互いに素なキーセットのエントリを上書きします。 これら 2 つのケースでは, Map を使用すると,別の Mutex または RWMutex とペアにした Go マップと比較して,ロック競合が大幅に減少する可能性があります。

ゼロ Map は空であり,使用する準備ができています。 最初の使用後に Map をコピーしてはいけません。

type Map struct {
    // エクスポートされていないフィールドがあります
}

func (*Map) Delete 1.9

func (m *Map) Delete(key interface{})

Delete はキーの値を削除します。

func (*Map) Load 1.9

func (m *Map) Load(key interface{}) (value interface{}, ok bool)

Load はマップに格納されているキーの値を返します。 値が存在しない場合は nil を返します。 ok の結果は,値がマップに見つかったかどうかを示します。

func (*Map) LoadOrStore 1.9

func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)

LoadOrStore は,存在する場合はキーの既存の値を返します。 そうでなければ,与えられた値を格納して返します。 ロードされた結果は,値がロードされた場合は true ,格納されている場合は false です。

func (*Map) Range 1.9

func (m *Map) Range(f func(key, value interface{}) bool)

Range は,マップに存在する各キーと値について順次 f を呼び出します。 f が false を返すと, range は反復を停止します。

Range は必ずしもマップの内容の一貫したスナップショットに対応するわけではありません。 キーを複数回訪問することはありませんが,任意のキーの値が平行に保存または削除されると,Range は, Range 呼び出し中のどの時点でもそのキーのマッピングを反映する可能性があります。

f が一定数の呼び出しの後で false を返したとしても, Range はマップ内の要素数で O(N) になることがあります。

func (*Map) Store 1.9

func (m *Map) Store(key, value interface{})

Store はキーの値を設定します。

type Mutex

Mutex は相互排除ロックです。 Mutex のゼロ値は,ロックされていないミューテックスです。

Mutex は最初の使用後にコピーしてはいけません。

type Mutex struct {
    // エクスポートされていないフィールドがあります
}

func (*Mutex) Lock

func (m *Mutex) Lock()

ロックロックロックがすでに使用されている場合は,ミューテックスが使用可能になるまで呼び出し側の goroutine がブロックします。

func (*Mutex) Unlock

func (m *Mutex) Unlock()

Unlock はロックを解除します。 m が Unlock への入り口でロックされていない場合は,ランタイムエラーです。

ロックされたミューテックスは,特定のゴルーチンと関連付けられていません。 1 つのゴルーチンがミューテックスをロックしてから,別のゴルーチンがそれをアンロックするように手配することができます。

type Once

一度は正確に 1 つのアクションを実行するオブジェクトです。

type Once struct {
    // エクスポートされていないフィールドがあります
}

コード:

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
}
// 出力 :1 回のみ

func (*Once) Do

func (o *Once) Do(f func())

Do は, Once のこのインスタンスに対して初めて呼び出される場合に限り,関数 f を呼び出します。言い換えれば,

var once Once

で, once.Do(f) が複数回呼び出された場合,たとえ f が各呼び出しにおいて異なる値を持っていても,最初の呼び出しだけが f を呼び出します。 各関数を実行するには, Once の新しいインスタンスが必要です。

Do は,一度だけ実行する必要がある初期化のためにあります。 f は引数がない関数なので, Do によって呼び出される関数への引数をキャプチャするために関数リテラルを使う必要があるかもしれません。

f への 1 回の呼び出しが戻るまで Do への呼び出しは返されないため, f が Do を呼び出した場合,デッドロックになります。

f パニックが発生した場合, Do はそれが戻ったと見なします。 Do の将来の呼び出しは f を呼び出さずに戻ります。

type Pool 1.3

Pool は,個別に保存および取得できる一連の一時オブジェクトです。

プールに保存されているアイテムは,通知なしにいつでも自動的に削除されることがあります。 これが発生したときにプールが唯一の参照を保持している場合,アイテムは割り当て解除される可能性があります。

Pool は,複数のゴルーチンが平行に使用しても安全です。

Pool の目的は,割り当てられているが未使用のアイテムを後で再利用できるようにキャッシュすることで,ガベージコレクタへの負担を軽減します。 つまり,効率的でスレッドセーフな空きリストを簡単に作成できます。 ただし,すべての空きリストに適しているわけではありません。

プールの適切な使用は,パッケージの平行の独立したクライアント間でサイレントに共有され,潜在的に再利用される一時的なアイテムのグループを管理することです。 プールは,多くのクライアントにわたる割り当てオーバーヘッドを償却する方法を提供します。

プールの有効な使用例は fmt パッケージにあります。 このパッケージは動的サイズの一時出力バッファを保持します。 店舗は負荷を受けて拡大縮小し (多くのゴルーチンが活発に表示しているとき) ,休止すると縮小します。

一方,短命のオブジェクトの一部として維持されている空きリストは,プールには適していません。 そのシナリオではオーバーヘッドが十分に償却されないためです。 そのようなオブジェクトに独自の空きリストを実装させる方が効率的です。

最初の使用後にプールをコピーしてはいけません。

type Pool struct {

    // New は, Get がそうでなければ nil を返すときに値を生成する関数をオプションで指定します。
    // Get の呼び出しと平行に変更することはできません。
    New func() interface{}
    // エクスポートされていないフィールドがあります
}

コード:

package sync_test

import (
    "bytes"
    "io"
    "os"
    "sync"
    "time"
)

var bufPool = sync.Pool{
    New: func() interface{} {
        // Pool の New 関数は一般にポインタ型のみを返すべきです,なぜならポインタは割り当てなしで戻りインターフェース値に入れることができるからです。
        return new(bytes.Buffer)
    },
}

// timeNow は time のテスト用偽バージョンです。
func timeNow() time.Time {
    return time.Unix(1136214245, 0)
}

func Log(w io.Writer, key, val string) {
    b := bufPool.Get().(*bytes.Buffer)
    b.Reset()
    // これを実際のロガーの time.Now() に置き換えます。
    b.WriteString(timeNow().UTC().Format(time.RFC3339))
    b.WriteByte(' ')
    b.WriteString(key)
    b.WriteByte('=')
    b.WriteString(val)
    w.Write(b.Bytes())
    bufPool.Put(b)
}

func ExamplePool() {
    Log(os.Stdout, "path", "/search?q=flowers")
    // 出力 : 2006-01-02T15:04:05Z パス =/search?q=flowers
}

func (*Pool) Get 1.3

func (p *Pool) Get() interface{}

Get はプールから任意の項目を選択し,それをプールから削除して呼び出し元に返します。 Get はプールを無視して空として扱うことを選択できます。 呼び出し側は, Put に渡された値と Get によって返された値の間の関係を想定してはいけません。

そうでなければ Get が nil を返し, p.New が nil 以外であれば, Get は p.New を呼び出した結果を返します。

func (*Pool) Put 1.3

func (p *Pool) Put(x interface{})

Put はプールに x を加算します。

type RWMutex

RWMutex は,リーダー / ライターの相互排他ロックです。 ロックは,任意の数のリーダーまたは 1 つのライターによって保持できます。 RWMutex のゼロ値は,ロック解除されたミューテックスです。

RWMutex は最初の使用後にコピーしてはいけません。

あるゴルーチンが読み取り用に RWMutex を保持していて,別のゴルーチンが Lock を呼び出す可能性がある場合,最初の読み取りロックが解放されるまで,どの goroutine も読み取りロックを取得できないと考えてください。 特に,これは再帰的な読み取りロックを禁止します。 これは,ロックが最終的に使用可能になるようにするためです。 ロックされたロックコールは,新しいリーダーがロックを取得することを除外します。

type RWMutex struct {
    // エクスポートされていないフィールドがあります
}

func (*RWMutex) Lock

func (rw *RWMutex) Lock()

Lock は,書き込みをロックします。 ロックが読み取りまたは書き込み用にすでにロックされている場合, Lock はロックが使用可能になるまでブロックします。

func (*RWMutex) RLock

func (rw *RWMutex) RLock()

RLock は読み取り用に rw をロックします。

再帰的な読み取りロックには使用しないでください。 ロックされたロックコールは,新しいリーダーがロックを取得することを除外します。 RWMutex 型に関するドキュメントを参照してください。

func (*RWMutex) RLocker

func (rw *RWMutex) RLocker() Locker

RLocker は, rw.RLock および rw.RUnlock を呼び出すことによって, Lock および Unlock メソッドを実装する Locker インターフェースを返します。

func (*RWMutex) RUnlock

func (rw *RWMutex) RUnlock()

RUnlock は 1 つの RLock 呼び出しを取り消します。 他の平行リーダーには影響しません。 rw が RUnlock への入り口で読み取り用にロックされていない場合は,ランタイムエラーです。

func (*RWMutex) Unlock

func (rw *RWMutex) Unlock()

Unlock は,書き込みのために rw のロックを解除します。 Unlock に入るときに rw が書き込み用にロックされていないと,ランタイムエラーになります。

ミューテックスと同様に,ロックされた RWMutex は特定のゴルーチンと関連付けられていません。 あるゴルーチンは, RWMutex を RLock (ロック) してから,別のゴルーチンを RUnlock (ロック解除) するように手配します。

type WaitGroup

WaitGroup はゴルーチンのコレクションが終了するのを待ちます。 メインのゴルーチンは Add を呼び出して待つゴルーチンの数を設定します。 その後,各ゴルーチンが実行され,終了したら Done を呼び出します。 平行に, Wait はすべてのゴルーチンが終了するまでブロックするために使用することができます。

WaitGroup は最初の使用後にコピーしてはいけません。

type WaitGroup struct {
    // エクスポートされていないフィールドがあります
}

この例では, WaitGroup を使用してすべての取得が完了するまでブロックするようにして,複数の URL を平行に取得します。

コード:

var wg sync.WaitGroup
var urls = []string{
    "http://www.golang.org/",
    "http://www.google.com/",
    "http://www.somestupidname.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()

func (*WaitGroup) Add

func (wg *WaitGroup) Add(delta int)

Add は, WaitGroup カウンタに負の値のデルタを追加します。 カウンタがゼロになると,待機中にブロックされていたすべてのゴルーチンが解放されます。 カウンターが負になれば,Add はパニックします。

カウンタがゼロのときに発生する正のデルタを使用した呼び出しは,待機の前に発生する必要があります。 負のデルタを使用したコール,またはカウンタが 0 より大きいときに開始される正のデルタを使用したコールは,いつでも発生する可能性があります。 通常これは, Add の呼び出しは,ゴルーチンを作成するステートメントやその他の待機中のイベントの前に実行する必要があることを意味します。 WaitGroup がいくつかの独立したイベントのセットを待つために再利用される場合,新しい Add 呼び出しは前のすべての Wait 呼び出しが戻った後に行われなければなりません。 WaitGroup の例を参照してください。

func (*WaitGroup) Done

func (wg *WaitGroup) Done()

Done は, WaitGroup カウンタを 1 つ減らします。

func (*WaitGroup) Wait

func (wg *WaitGroup) Wait()

Wait は,WaitGroup カウンタがゼロになるまでブロックします。

サブディレクトリ

名前 概要
..
atomic atomic パッケージは,同期アルゴリズムを実装する際に役立つ低レベルのアトミック基本要素を提供します。