Sobes.tech
Senior

Tell me more about semaphores.

sobes.tech AI

Answer from AI

Semaphores are synchronization primitives used to control access to shared resources in multithreaded or concurrent environments. In Go, semaphores are not built directly into the standard library, but they can be implemented using channels.

The main idea of a semaphore is to limit the number of operations or threads that can access a resource simultaneously. For example, if you have a pool of 3 database connections, a semaphore with a maximum count of 3 will allow no more than three connections to be used at the same time.

An example implementation of a semaphore in Go using channels:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    // Create a semaphore with capacity 3
    sem := make(chan struct{}, 3)
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            sem <- struct{}{} // acquire semaphore
            fmt.Printf("Goroutine %d started work\n", id)
            time.Sleep(1 * time.Second) // simulate work
            fmt.Printf("Goroutine %d finished work\n", id)
            <-sem // release semaphore
        }(i)
    }

    wg.Wait()
}

In this example, no more than 3 goroutines will run simultaneously; the rest will wait for the semaphore to be released.

Thus, semaphores are useful for limiting parallelism and preventing race conditions when accessing limited resources.