Documentation ¶
Overview ¶
Package semaphore provides a weighted semaphore implementation.
Example (WorkerPool) ¶
Example_workerPool demonstrates how to use a semaphore to limit the number of goroutines working on parallel tasks.
This use of a semaphore mimics a typical “worker pool” pattern, but without the need to explicitly shut down idle workers when the work is done.
package main import ( "context" "fmt" "log" "runtime" "golang.org/x/sync/semaphore" ) // Example_workerPool demonstrates how to use a semaphore to limit the number of // goroutines working on parallel tasks. // // This use of a semaphore mimics a typical “worker pool” pattern, but without // the need to explicitly shut down idle workers when the work is done. func main() { ctx := context.TODO() var ( maxWorkers = runtime.GOMAXPROCS(0) sem = semaphore.NewWeighted(int64(maxWorkers)) out = make([]int, 32) ) // Compute the output using up to maxWorkers goroutines at a time. for i := range out { // When maxWorkers goroutines are in flight, Acquire blocks until one of the // workers finishes. if err := sem.Acquire(ctx, 1); err != nil { log.Printf("Failed to acquire semaphore: %v", err) break } go func(i int) { defer sem.Release(1) out[i] = collatzSteps(i + 1) }(i) } // Acquire all of the tokens to wait for any remaining workers to finish. // // If you are already waiting for the workers by some other means (such as an // errgroup.Group), you can omit this final Acquire call. if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil { log.Printf("Failed to acquire semaphore: %v", err) } fmt.Println(out) } // collatzSteps computes the number of steps to reach 1 under the Collatz // conjecture. (See https://en.wikipedia.org/wiki/Collatz_conjecture.) func collatzSteps(n int) (steps int) { if n <= 0 { panic("nonpositive input") } for ; n > 1; steps++ { if steps < 0 { panic("too many steps") } if n%2 == 0 { n /= 2 continue } const maxInt = int(^uint(0) >> 1) if n > (maxInt-1)/3 { panic("overflow") } n = 3*n + 1 } return steps }
Output: [0 1 7 2 5 8 16 3 19 6 14 9 9 17 17 4 12 20 20 7 7 15 15 10 23 10 111 18 18 18 106 5]
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrMaxWaiters = errors.New("too many waiters")
ErrMaxWaiters is returned when Acquire is called, but there are more than maxWaiters waiters.
Functions ¶
This section is empty.
Types ¶
type Weighted ¶
type Weighted struct {
// contains filtered or unexported fields
}
Weighted provides a way to bound concurrent access to a resource. The callers can request access with a given weight.
func NewWeighted ¶
NewWeighted creates a new weighted semaphore with the given maximum combined weight for concurrent access. maxWaiters provides a limit such that calls to Acquire will immediately error if the number of waiters is that high. A maxWaiters of zero means no limit.
func (*Weighted) Acquire ¶
Acquire acquires the semaphore with a weight of n, blocking until resources are available or ctx is done. On success, returns nil. On failure, returns ctx.Err() and leaves the semaphore unchanged.
If ctx is already done, Acquire may still succeed without blocking.
If there are maxWaiters waiters, Acquire will return an error immediately.
func (*Weighted) NumWaiters ¶
func (*Weighted) TryAcquire ¶
TryAcquire acquires the semaphore with a weight of n without blocking. On success, returns true. On failure, returns false and leaves the semaphore unchanged.