Golang concurrency: Difference between revisions

From wikinotes
No edit summary
Line 65: Line 65:
Channels are typed, and you may optionally restrict it to direction (ex. read/write only).
Channels are typed, and you may optionally restrict it to direction (ex. read/write only).


Channels are FIFOs.
Create channel
 
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
ch := make(chan int) // create a channel that passes ints
ch := make(chan int) // create a channel that passes ints
</syntaxhighlight>


Read/write channel
<syntaxhighlight lang="go">
num := <- ch  // read next item in channel
num := <- ch  // read next item in channel
ch <- 123    // append next item to channel
ch <- 123    // append next item to channel
</syntaxhighlight>
</syntaxhighlight>


You can specify the direction of the information flow in a method signature
Channel direction in a method signature
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
go func(ch <-chan int) { ... } // read-only channel
go func(ch <-chan int) { ... } // read-only channel

Revision as of 20:35, 6 June 2022

This page is about the methods of concurrency provided by go.
If you're looking for synchronization primitives (ex. mutexes, semaphores, ... see golang synchronization)

Not Present

Go does not:

  • expose OS-threads, you only have access to it's green-threads
  • abstract multiprocessing, but you could roll your own with a subprocess and IPC if you wanted to
  • provide a message-queue implementation, use channels instead

Goroutines

Usage

Goroutines use green-threads rather than os-threads.
An OS thread is relatively expensive in setup and memory. One thread is reserved for a particular stack.
Go abstracts threads/threadpools with goroutines to make threads relatively cheap.

func doThing() {
    fmt.Println("hi")
}

func main() {
    go sayHello()  // <-- run in thread
}

Go functions default to using value objects rather than references.
Depending on your datastructure, this makes goroutines fairly concurrency-safe, since it operates on a copy of the data, rather than the same data.

func printThing(a string) {
    fmt.Println(a)
}

go printThing("abc")

Testing

go run -race foo.go  # run, checking for race conditions

Limits

Threads are a finite resource. You only have so many CPU cores, and CPU cores can only evaluate one thread at a time. Go defaults to allowing one thread per core, but you can generally get additional performance by increasing this.

require "runtime"

runtime.GOMAXPROCS(-1)  // show configured max-number of threads
runtime.GOMAXPROCS(2)   // set max-number of threads

Channels

Channels serve as a message queue for it's goroutines.
Channels are typed, and you may optionally restrict it to direction (ex. read/write only).

Create channel

ch := make(chan int) // create a channel that passes ints

Read/write channel

num := <- ch  // read next item in channel
ch <- 123     // append next item to channel

Channel direction in a method signature

go func(ch <-chan int) { ... } // read-only channel
go func(ch chan<- int) { ... } // write-only channel