DEV Community

Perm Chao
Perm Chao

Posted on

Implement semaphore in golang by buffered channel

Cover

Getting started

1) make buffered channel

sem := make(chan int, 10)
Enter fullscreen mode Exit fullscreen mode

2) in synchronous process, send some variable to buffered channel (this step called acquire)

sem <- i
Enter fullscreen mode Exit fullscreen mode

3) in asynchronous process, release variable from buffered channel (this step called release)

<- sem
Enter fullscreen mode Exit fullscreen mode

Result from log

start   process [9]
start   process [0]
start   process [7]
start   process [6]
start   process [3]
start   process [2]
start   process [4]
start   process [8]
start   process [1]
start   process [5] <- 10 processes start concurrency
end     process [0]      0.0001 seconds
start   process [10] <- process 10 start after process 0 end
end     process [2]      4.0014 seconds
end     process [1]      4.0012 seconds
start   process [12]
start   process [11] <- process 11, 12 start after process 1, 2 end
end     process [3]      5.0011 seconds
start   process [13]
end     process [4]      0.0001 seconds
start   process [14]
end     process [5]      6.0014 seconds
start   process [15]
end     process [6]      1.0011 seconds
start   process [16]
end     process [7]      8.0013 seconds
start   process [17]
...
Enter fullscreen mode Exit fullscreen mode

Remark

Standard package
golang.org/x/sync/semaphore


Code

package main

import (
    "fmt"
    "math/rand"
    "time"
)

const (
    MAX_CONCURRENT     = 10   // Allow max concurrent
    TOTAL_PROCESSES    = 1000 // Total loop count
    MAX_RANDOM_SECONDS = 20
)

func main() {
    sem := make(chan int, MAX_CONCURRENT)
    for i := range TOTAL_PROCESSES {
        sem <- i // *** send i to buffered channel. If channel sem full, it blocked for loop.
        go func(i int) {
            start := time.Now()
            fmt.Printf("start\tprocess\t[%d]\n", i)
            defer func() {
                // <- sem will release a value, so sem channel will available for next value
                fmt.Printf("end\tprocess\t[%d]\t %.4f seconds\n", <-sem, time.Since(start).Seconds())
            }()
            iv := rand.Intn(MAX_RANDOM_SECONDS) * int(time.Second)
            time.Sleep(time.Duration(iv))
        }(i)
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
robert133585622603650 profile image
Robert

Hello web3 explorer! take your awesome around $15 in BNB-based tokens ASAP! — Be part of the airdrop! Reward available after wallet connection. 👉 duckybsc.xyz

Some comments may only be visible to logged-in visitors. Sign in to view all comments.