Metered concurrency: Difference between revisions

(→‎Go, Buffered channel: small improvement to code, more explanation.)
Line 606:
=={{header|Go}}==
===Buffered channel===
Recommended solution for simplicity. Acquire operation is channel send, release is channel receive, and count is provided with cap and len(channel).
 
To demonstrate, this example implements the [https://en.wikipedia.org/wiki/Semaphore_(programming)#Library_analogy Library analogy] from Wikipedia with 10 study rooms and 20 students.
Line 621:
"time"
)
 
// counting semaphore implemented with a buffered channel
type sem chan struct{}
 
func (s sem) acquire() { roomss <- struct{}{} }
func (s sem) release() { <-s }
func (s sem) count() int { return cap(s) - len(s) }
 
// log package serializes output
Line 630 ⟶ 637:
 
func main() {
rooms := make(chan struct{}sem, nRooms)
// buffered channel used as a counting semaphore
rooms := make(chan struct{}, nRooms)
for i := 0; i < nRooms; i++ {
rooms <- struct{}{}
}
// WaitGroup used to wait for all students to have studied
// before terminating program
Line 646 ⟶ 649:
}
 
func student(rooms chan struct{}sem, studied *sync.WaitGroup) {
<-rooms // .acquire operation()
// report per task descrption. also exercise count operation
fmt.Printf("Room entered. Count is %d. Studying...\n",
len(rooms.count()) // len function provides count operation
time.Sleep(2 * time.Second) // sleep per task description
rooms <- struct{}{} // .release operation()
studied.Done() // signal that student is done
}</lang>
Output for this and the other Go programs here shows 10 students studying immediately, about a 2 second pause, 10 more students studying, then another pause of about 2 seconds before returning to the command prompt. In this example the count values may look jumbled. This is a result of the student goroutines running concurrently.
1,707

edits