Metered concurrency: Difference between revisions

Content added Content deleted
No edit summary
(→‎Buffered channel: bug fix. previous version worked with existing compiler but was technically invalid.)
Line 414: Line 414:
Recommended solution for simplicity. Acquire operation is channel send, release is channel receive, and count is provided with len(channel). Also WaitGroup used as a completion checkpoint.
Recommended solution for simplicity. Acquire operation is channel send, release is channel receive, and count is provided with len(channel). Also WaitGroup used as a completion checkpoint.
<lang go>package main
<lang go>package main

import (
import (
"log"
"log"
Line 421: Line 421:
"time"
"time"
)
)

// log package serializes output
// log package serializes output
var fmt = log.New(os.Stdout, "", 0)
var fmt = log.New(os.Stdout, "", 0)

// library analogy per WP article
const nRooms = 10
const nRooms = 10
const nStudents = 20
const nStudents = 20

func main() {
func main() {
// library analogy per WP article
// buffered channel used as a counting semaphore
librarian := make(chan int, nRooms)
rooms := make(chan int, nRooms)
for i := 0; i < nRooms; i++ {
rooms <- 1
}
// WaitGroup used to wait for all students to have studied
// before terminating program
var studied sync.WaitGroup
var studied sync.WaitGroup
studied.Add(nStudents)
studied.Add(nStudents)
// nStudents run concurrently
for i := 0; i < nStudents; i++ {
for i := 0; i < nStudents; i++ {
go student(librarian, &studied)
go student(rooms, &studied)
}
}
// wait until all students have studied before terminating program
studied.Wait()
studied.Wait()
}
}

func student(studyRoom chan int, studied *sync.WaitGroup) {
func student(rooms chan int, studied *sync.WaitGroup) {
studyRoom <- 1 // acquire operation
<-rooms // acquire operation
// report per task descrption. also exercise count operation
// report per task descrption. also exercise count operation
fmt.Printf("Room entered. Count is %d. Studying...\n",
fmt.Printf("Room entered. Count is %d. Studying...\n",
nRooms-len(studyRoom)) // len function provides count operation
len(rooms)) // len function provides count operation
time.Sleep(2 * time.Second) // sleep per task description
time.Sleep(2 * time.Second) // sleep per task description
<-studyRoom // release operation
rooms <- 1 // release operation
studied.Done() // signal done
studied.Done() // signal that student is done
}</lang>
}</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.
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.

===Sync.Cond===
===Sync.Cond===
A more traditional approach implementing a counting semaphore object with sync.Cond. It has a constructor and methods for the three operations requested by the task.
A more traditional approach implementing a counting semaphore object with sync.Cond. It has a constructor and methods for the three operations requested by the task.