C source code compiles on Plan 9 from User Space: #include "u.h" #include "libc.h" #include "thread.h" enum { STACK = 8192 }; void producer(void *v) { Channel *ch = v; for (uint i = 1; ; ++i) { sleep(400); print("p %d\n", i); sendul(ch, i); } } void consumer(void *v) { Channel *ch = v; for (;;) { uint p = recvul(ch); print("\t\tc %d\n", p); sleep(200 + nrand(600)); } } void threadmain(int argc, char **argv) { int (*mk)(void (*fn)(void*), void *arg, uint stack); mk = threadcreate; Channel *ch = chancreate(sizeof(ulong), 1); mk(producer, ch, STACK); mk(consumer, ch, STACK); recvp(chancreate(sizeof(void*), 0)); threadexitsall(0); } The program entry point is at function threadmain. The function call ch = chancreate(sizeof(ulong), 1) creates the channel, the function call sendul(ch, i) sends a value into the channel and the function call p = recvul(ch) receives a value from the channel. The programming language Go has channels, too. A Go example: package main import ( "fmt" "math/rand" "time" ) var sendMsg = 0 func produceMessage() int { time.Sleep(400 * time.Millisecond) sendMsg++ fmt.Printf("sendMsg = %v\n", sendMsg) return sendMsg } func consumeMessage(recvMsg int) { fmt.Printf("\t\trecvMsg = %v\n", recvMsg) time.Sleep(time.Duration(200+rand.Intn(600)) * time.Millisecond) } func main() { ch := make(chan int, 3) go func() { for { ch <- produceMessage() } }() for recvMsg := range ch { consumeMessage(recvMsg) } } The Go producer-consumer solution uses the main Go routine for consumer and creates a new, unnamed Go routine for the producer. The two Go routines are connected with channel ch. This channel can queue up to three int values. The statement ch := make(chan int, 3) creates the channel, the statement ch <- produceMessage() sends a value into the channel and the statement recvMsg := range ch receives a value from the channel. The allocation of memory resources, the allocation of processing resources, and the synchronization of resources are done by the programming language automatically. Without semaphores or monitors Leslie Lamport documented a bounded buffer producer-consumer solution for one producer and one consumer: We assume that the buffer can hold at most b messages, b >= 1. In our solution, we let k be a constant greater than b, and let s and r be integer variables assuming values between 0 and k-1. We assume that initially s=r and the buffer is empty. By choosing k to be a multiple of b, the buffer can be implemented as an array B [0: