The Producer-Consumer problem is an operating system problem. Here, the producer produces a message and passes it to the buffer. The consumer stores that message from the buffer and removes it from the buffer.
For better understanding, let’s explore an illustration.
In the illustration above, we have a producer that passes the data to a buffer. The consumer stores that data and removes it from the buffer.
Let's look at an example to learn its implementation in Go.
package main import ( "runtime/pprof" "flag" "log" "fmt" "runtime" "os" ) // Producer definition type Producer struct { text *chan int done *chan bool } // produce start creating message and send it through channel func (p *Producer) produce(max int) { fmt.Println("Producer start message sending") for i := 0; i < max; i++ { fmt.Println("Message send by Producer ", i) *p.text <- i } *p.done <- true // updates when message produced fmt.Println("Producer message ends") } type Consumer struct { text *chan int } // consume reads the text channel func (c *Consumer) consume() { fmt.Println("consumer start recieving message") for { message := <-*c.text fmt.Println("Message recieved by consumer", message) } } func main() { // profile flags cpuflag := flag.String("cpuflag", "", "update cpu profile to `file`") memflag := flag.String("memflag", "", "update memory profile to the `file`") // Get the max number from flag max := flag.Int("n", 4, "Show message count") flag.Parse() // To create the maximum number of cores in the processor runtime.GOMAXPROCS(runtime.NumCPU()) // CPU Profile creation if *cpuflag != "" { f, err := os.Create(*cpuflag) if err != nil { log.Fatal("Enable to create CPU profile: ", err) } if err := pprof.StartCPUProfile(f); err != nil { log.Fatal("Enable to start CPU profile: ", err) } defer pprof.StopCPUProfile() } var text = make(chan int) // channel send its messages var done = make(chan bool) // channel to intimate when production is done //creating a Producer //Start a goroutine for Produce.produce producer := &Producer{text: &text, done: &done} go producer.produce(*max) //creating a Consumer //Start a goroutine for Consumer.consume consumer := &Consumer{text: &text} go consumer.consume() // End the program when the production is complete <-done // Memory profile creation if *memflag != "" { f, err := os.Create(*memflag) if err != nil { log.Fatal("Enable to create memory id: ", err) } runtime.GC() // get update on status if err := pprof.WriteHeapProfile(f); err != nil { log.Fatal("Enable to write memory id: ", err) } f.Close() } }
runtime/pprof
, flag
, log
, fmt
, runtime
, and os
packages.int
and bool
types for the Producer
to transfer data using the chan
keyword.produce
, to send messages to consumers. We terminate it on the *p.done <-true
condition.int
type channel for the Consumer
to read the message.consume
for the Consumer
, which shows the received messages.cpuflag
: This is to update the CPU profile to the file.memflag
: This is to update the memory profile.parse.flag
to get the values from the flags.runtime.GOMAXPROCS(runtime.NumCPU())
to create the maximum cores from the processor.if
condition to implement cpuflag
and identify if any error occurs.text
and done
variables to send a message and get an intimation on sending the message.Producer
, and call the Producer
function.Consumer
, and call the Consumer
function.<-done
to end the program from the producer's side.if
condition to implement memflag
and identify if any error occurs.RELATED TAGS
CONTRIBUTOR
View all Courses