Home

Published

- 2 min read

sync.Semaphore

img of sync.Semaphore

Background

sem.Acquire(context.Background(), 1)

Concurrency helps us complete tasks faster, however, sometimes too much concurrency breaks things.

Semaphore allows us to control our concurrency.

ELI5 Why we need it

Imagine trying to cross a shaky, old wooden bridge. Experts have verified it to be safe for 10 people to be crossing at the same time, however, what happens if 100 people cross the bridge at the same time? It will very likely break.

In this case, each person crossing the bridge is 1 concurrency and we want to limit concurrency to max 10.

How to use it

First, let us define a function to mimic a person crossing a bridge:

// BoardBus mimics the time taken for a person to board a bus
func crossBridge() {
	time.Sleep(1*time.Second)
}

Now, we can test how long it takes 100 people to cross a bridge that only allows 10 people at any time.

func simulateHundredPeopleCrossBridge() {
	ts:= time.Now()
	sem := semaphore.NewWeighted(10) // declare semaphore with 10 slots
	wg := sync.WaitGroup{}
	for i := 0 ; i< 100 ; i++ {
		wg.Add(1)
		go func ()  {
			sem.Acquire(context.Background(), 1) // try to get 1 slot
			crossBridge()
			wg.Done()
			sem.Release(1) // release 1 slot
		}()

	}
	wg.Wait()
	fmt.Println(time.Since(ts).Seconds())
}
// Output: 10.001244

Roughly 10 seconds as expected. Let’s list the key components here:

  1. semaphore.NewWeighted(10)
  2. sem.Acquire(context.Background(), 1)
  3. sem.Release(1)

semaphore.NewWeighted(10)

This initializes a semaphore with 10 slots, which we will use to control the number of concurrency.

sem.Acquire(context.Background(), 1)

Before any person crosses a bridge, he/she will have to acquire a slot from the semaphore before crossing. If there are no slots, the person(goroutine) will wait until they get 1.

sem.Release(1)

After crossing a bridge, the person will return the slot back to the semaphore.

Rabbit Hole

Try implementing semaphores using go channels.

Alright, that is all for today. Let’s get one post smarter every day, and see you tomorrow! sem.Release(1)

https://pkg.go.dev/golang.org/x/sync/semaphore

Subscribe

* indicates required

Intuit Mailchimp