sync

package
v1.21.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 7, 2024 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

パッケージsyncは相互排他ロックなどの基本的な同期プリミティブを提供します。OnceとWaitGroup以外の型は、低レベルのライブラリルーチンでの使用を意図しています。より高レベルな同期はチャネルと通信を介して行う方が良いです。

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

Index

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 NewCond

func NewCond(l Locker) *Cond

NewCondはLocker lを持つ新しいCondを返します。

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 Locker

type Locker interface {
	Lock()
	Unlock()
}

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

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

func (m *Map) CompareAndDelete(key, old any) (deleted bool)

CompareAndDeleteは、keyの値がoldと等しい場合、そのエントリを削除します。 oldの値は比較可能な型である必要があります。

マップにkeyの現在の値がない場合、CompareAndDeleteはfalseを返します(oldの値がnilインターフェース値であっても)。

func (*Map) CompareAndSwap added in v1.20.0

func (m *Map) CompareAndSwap(key, old, new any) bool

CompareAndSwapは、キーの古い値と新しい値を交換します。 マップに格納されている値が古い値と等しい場合にのみ行われます。 古い値は比較可能な型でなければなりません。

func (*Map) Delete added in v1.9.0

func (m *Map) Delete(key any)

Deleteは指定されたキーの値を削除します。

func (*Map) Load added in v1.9.0

func (m *Map) Load(key any) (value any, ok bool)

Loadは、キーに対応するマップ内の値を返します。もし値が存在しない場合はnilを返します。 okの結果は、値がマップ内で見つかったかどうかを示します。

func (*Map) LoadAndDelete added in v1.15.0

func (m *Map) LoadAndDelete(key any) (value any, loaded bool)

LoadAndDelete はキーに対応する値を削除し、もし値が存在する場合は以前の値を返します。 読み込まれた結果はキーが存在するかどうかを報告します。

func (*Map) LoadOrStore added in v1.9.0

func (m *Map) LoadOrStore(key, value any) (actual any, loaded bool)

LoadOrStore は、キーが存在する場合は既存の値を返します。 それ以外の場合は、指定された値を格納して返します。 読み込まれた結果が true の場合、値は読み込まれ、false の場合は格納されました。

func (*Map) Range added in v1.9.0

func (m *Map) Range(f func(key, value any) bool)

Rangeはマップ内の各キーと値に対して順番にfを呼び出します。 もしfがfalseを返す場合、Rangeは繰り返しを停止します。

RangeはMapの内容に一貫したスナップショットに必ずしも対応していません: 各キーは複数回訪れませんが、任意のキーの値が同時に格納または削除される場合(fによっても含まれます)、 RangeはRange呼び出し中の任意の時点からのそのキーのマッピングを反映することがあります。 Rangeはレシーバー上の他のメソッドをブロックしません。f自体もmの任意のメソッドを呼び出すことができます。

fが一定回数の呼び出し後にfalseを返す場合でも、Rangeはマップ内の要素数の数に比例するO(N)の可能性があります。

func (*Map) Store added in v1.9.0

func (m *Map) Store(key, value any)

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

func (*Map) Swap added in v1.20.0

func (m *Map) Swap(key, value any) (previous any, loaded bool)

Swapはキーの値を入れ替え、以前の値(あれば)を返します。 読み込まれた結果は、キーが存在するかどうかを報告します。

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 をロックします。 もし既にロックが使用中である場合、呼び出し元のゴルーチンは ミューテックスが利用可能になるまでブロックされます。

func (*Mutex) TryLock added in v1.18.0

func (m *Mutex) TryLock() bool

TryLock はmをロックしようとし、成功したかどうかを報告します。

TryLockの正しい使用方法が存在することに注意してくださいが、それらはまれであり、 TryLockの使用はしばしばミューテックスの特定の使用において深刻な問題の兆候です。

func (*Mutex) Unlock

func (m *Mutex) Unlock()

Unlockはmをアンロックします。 mがUnlockされる前にロックされていない場合、ランタイムエラーになります。

ロックされたMutexは特定のゴルーチンに関連付けられていません。 あるゴルーチンがMutexをロックし、別のゴルーチンがそれをアンロックするようにすることも許可されています。

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

func (*Pool) Get added in v1.3.0

func (p *Pool) Get() any

GetはPoolからランダムなアイテムを選択し、Poolから削除して呼び出し元に返します。 Getはプールを無視して空として扱うことを選択する場合があります。 Putに渡された値とGetが返す値の間には、呼び出し元は何の関係も仮定すべきではありません。

Getが通常nilを返す場合であり、p.Newがnilでない場合、Getはp.Newを呼び出した結果を返します。

func (*Pool) Put added in v1.3.0

func (p *Pool) Put(x any)

xをプールに追加します。

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

func (rw *RWMutex) RLocker() Locker

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

func (rw *RWMutex) TryLock() bool

TryLockは、rwを書き込み用にロックしようとし、成功したかどうかを報告します。

TryLockの正しい使用法は存在しますが、それらはまれであり、 mutexの特定の使用法におけるより深刻な問題の兆候であることが多いため、 TryLockの使用は避けるべきです。

func (*RWMutex) TryRLock added in v1.18.0

func (rw *RWMutex) TryRLock() bool

TryRLockはrwを読み取りロックしようとし、成功したかどうかを報告します。

TryRLockの正しい使用方法は存在しますが、それらは稀であり、 TryRLockの使用はしばしばミューテックスの特定の使用法におけるより深刻な問題の兆候です。

func (*RWMutex) Unlock

func (rw *RWMutex) Unlock()

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

Mutexと同様に、ロックされたRWMutexは特定のゴルーチンに関連付けられていません。あるゴルーチンがRWMutexをRLock(Lock)し、別のゴルーチンがRUnlock(Unlock)するようにすることができます。

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

func (wg *WaitGroup) Add(delta int)

AddはWaitGroupのカウンターにデルタを追加します。デルタは負であることもあります。 カウンターがゼロになると、Waitでブロックされているすべてのゴルーチンが解放されます。 カウンターが負になると、Addはパニックを発生させます。

カウンターがゼロの状態で正のデルタで呼び出される場合は、Waitより前に実行される必要があることに注意してください。 負のデルタで呼び出される場合や、カウンターがゼロより大きい状態で正のデルタで呼ばれる場合は、任意のタイミングで発生する場合があります。 通常、これはAddの呼び出しは、ゴルーチンの作成または待機する他のイベントの直前に実行されるべきことを意味します。 WaitGroupが複数の独立したイベントセットを待機するために再利用される場合、新しいAdd呼び出しは以前のすべてのWait呼び出しが返された後に行われる必要があります。 WaitGroupの例を参照してください。

func (*WaitGroup) Done

func (wg *WaitGroup) Done()

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

func (*WaitGroup) Wait

func (wg *WaitGroup) Wait()

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

Directories

Path Synopsis
パッケージatomicは、同期アルゴリズムの実装に役立つ 低レベルのアトミックメモリプリミティブを提供します。
パッケージatomicは、同期アルゴリズムの実装に役立つ 低レベルのアトミックメモリプリミティブを提供します。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL