package semaphore
import "golang.org/x/sync/semaphore"
Package semaphore provides a weighted semaphore implementation.
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.
Code:play
Output:Example (WorkerPool)¶
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
}
[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 ¶
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.
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.
func (*Weighted) Release ¶
Release releases the semaphore with a weight of n.
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.
Source Files ¶
semaphore.go
- Version
- v0.11.0 (latest)
- Published
- Jan 17, 2025
- Platform
- linux/amd64
- Imports
- 3 packages
- Last checked
- 1 month ago –
Tools for package owners.