You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi.
Studying your semaphore implementation I have written this example.
I am wondering if it is compliant with your implementation, and if yes, if it is comparable to the D.Vyukov suggested example (effective go reviews). See in the following example:
/*
Counting Semaphore.
Binary Semaphore (Edsger Dijkstra) and Counting Semaphore (Carel S. Scholten)
are 2 variants of the Semaphore scheme.
A good and short (critical) presentation here: (http://bit.ly/1OCBY9t).
func Serve(queue chan *Request) {
for req := range queue {
sem <- 1 // Wait for active queue to drain the buffer of chan sem.
go func(req *Request) {
process(req)
<-sem // Done; enable next request to run.
}(req)
}
}
An alternative solution, was proposed by D.Vyukov:
It initiates a fixed number of Signals (sem <- 1), that limit the number of
started goroutines by construction.
func Serve(queue chan *Request) {
sem := make(chan int, MaxOutstanding)
for i := 0; i < MaxOutstanding; i++ {
sem <- 1
}
for req := range queue {
// acquisition of the semaphore must be on a channel receive, not a send.
//
<-sem
go func() {
process(req)
sem <- 1
}
}
}
In our example, this second approach is implemented using a Counting Semaphore.
See in the code below: Acquire(n) and Release(1) n times.
To be note: we are using the robust Semaphore implementation by R.Obryk,
available here: github.com/robryk/semaphore.
*/
package main
import (
"fmt"
"github.com/semaphore"
)
var (
// max number of goroutines launched concurrently
MaxOutstanding int = 4
// a list to process
list = []int{}
)
func main() {
for i:=1; i<=10; i++ {
list = append(list, i)
}
Serve(list)
}
// Observe the difference with the 1st Effective Go example (in comment above).
// In case of overload, a 'Wait' is organized limiting the number of concurrent
// goroutines: a go throttle.
//
func Serve(queue []int) {
s := semaphore.NewSemaphore(MaxOutstanding)
msg := make(chan string)
// Wait for goroutines to drain the 'counting semaphore',
// when drained: blocks until a 'next release'!
s.Acquire(MaxOutstanding)
// start n goroutines until the s.Acquire() blocks
for i, item := range queue {
go func(i, item int) {
// any processing here
text := fmt.Sprintf("from goroutine[%d]= %d\n", i, item)
msg <- text
// Done; enable next task to run (drain the counting semaphore of 1).
s.Release(1)
}(i, item)
}
for x:=0; x < len(list); x++ {
fmt.Printf(<-msg)
}
}
Thanks in advance for your feed-back.
The text was updated successfully, but these errors were encountered:
Hi.
Studying your semaphore implementation I have written this example.
I am wondering if it is compliant with your implementation, and if yes, if it is comparable to the D.Vyukov suggested example (effective go reviews). See in the following example:
/*
Counting Semaphore.
Binary Semaphore (Edsger Dijkstra) and Counting Semaphore (Carel S. Scholten)
are 2 variants of the Semaphore scheme.
A good and short (critical) presentation here: (http://bit.ly/1OCBY9t).
The example below, is a study of the "effective go" example of a channel used as
a semaphore (see https://golang.org/doc/effective_go.html#channels):
func Serve(queue chan *Request) {
for req := range queue {
sem <- 1 // Wait for active queue to drain the buffer of chan sem.
go func(req *Request) {
process(req)
<-sem // Done; enable next request to run.
}(req)
}
}
An alternative solution, was proposed by D.Vyukov:
It initiates a fixed number of Signals (sem <- 1), that limit the number of
started goroutines by construction.
func Serve(queue chan *Request) {
sem := make(chan int, MaxOutstanding)
for i := 0; i < MaxOutstanding; i++ {
sem <- 1
}
for req := range queue {
// acquisition of the semaphore must be on a channel receive, not a send.
//
<-sem
go func() {
process(req)
sem <- 1
}
}
}
In our example, this second approach is implemented using a Counting Semaphore.
See in the code below: Acquire(n) and Release(1) n times.
To be note: we are using the robust Semaphore implementation by R.Obryk,
available here: github.com/robryk/semaphore.
*/
package main
import (
"fmt"
)
var (
// max number of goroutines launched concurrently
MaxOutstanding int = 4
// a list to process
list = []int{}
)
func main() {
for i:=1; i<=10; i++ {
list = append(list, i)
}
Serve(list)
}
// Observe the difference with the 1st Effective Go example (in comment above).
// In case of overload, a 'Wait' is organized limiting the number of concurrent
// goroutines: a go throttle.
//
func Serve(queue []int) {
s := semaphore.NewSemaphore(MaxOutstanding)
msg := make(chan string)
}
Thanks in advance for your feed-back.
The text was updated successfully, but these errors were encountered: