The very first producer-consumer solution in the Electrologica computers used 'channels'. Hoare defined
channels: An alternative to explicit naming of source and destination would be to name a port through which communication is to take place. The port names would be local to the processes, and the manner in which pairs of ports are to be connected by channels could be declared in the head of a parallel command. Brinch Hansen implemented channels in the programming languages
Joyce and
Super Pascal. The Plan 9 operating system programming language
Alef, the Inferno operating system programming language
Limbo have channels. The following 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 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 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==