Synchronizing goroutines
via sync package
Ways of declaring goroutines
func main() {
go sayHello()
}
func sayHello() {
fmt.Println("hello")
}go func() {
fmt.Println("hello")
}() // <--- the anonymous function must be invoked immediatelysayHello := func() {
fmt.Println("hello")
}
go sayHello()To make sure your goroutines execute before the main goroutine we need join points. These can be created via:
WaitGroup primitive
for waiting for a set of concurrent operations to complete when you either don't care about the result of the concurrent operation, or you have other means of collecting their results
Closures = a function value that references variables from outside its body.
With closures, we'd have to pass a copy of the variable into the closure so by the time a goroutine is run, it will be operating on the data from its iteration of the loop.
Mutex
provides a concurrent-safe way to express exclusive access to these shared resources.
sync.Mutex interface with Lock() and Unlock() methods
Shares memory by creating a convention developers must follow to synchronise access to the memory.
RWMutex
same as Mutex but it provides a read/write lock. We can have a multiple number of readers holding a reader lock as long as nobody is holding a writer lock.
sync.RWMutex interface with RLock() and RUnlock() methods
RWMutex can only be held by n readers at a time, or by a single writer

Cond
a rendezvous point for goroutines waiting for or announcing the occurence of an event (=signal between 2 or more goroutines, has no info other than it happened).
sync.NewCond(&sync.Mutex{}) with 2 methods
Signal- notifies goroutines (runtime picks the one that has been waiting the longest) blocked on aWaitcall that the condition has been triggered
Brodcast - sends signal to all waiting goroutines
Once
ensures that only one call to Do ever calls the function passed in
counts the no of times Do is called, not how many unique functions passed into Do are called
Pool
= concurrent-safe implementation of the object pool pattern.
Get interface - checks wether the are any available instances within the pool to return to the caller, and if not, call its New member variable to create one.
Put interface - to put the instance they were working with back in the pool
Uses cases:
memory optimisations as instantiated objects are garbage collected.
warming up a cache of pre-allocated objects for operations that must run as quickly as possible. (by trying to guard the host machine's memory front-loading the time it takes to get a reference to another object)
Channels
can be used to synchronise access of the memory and to communicate information between goroutines.
Instantiating
support unidirectional flow of data:
channel that can only read
channel that can only send
Sending/Receiving
Channels are blocking.
Any goroutine that attempts to write to a channel that is full will wait until the channel has been emptied.
Any goroutine that attempts to read from a channel that is empty will wait until at least one item is placed on it.
Closing
Ranging over a channel
Closing a channel signals to multiple goroutines
Buffered Channels
channels that are given a capacity when they're instantiated.
Buffered channels are in-memory FIFO queue for concurrent processes to communicate over.
Result of channel operation given a channel's state
Read
nil
block
open and non empty
value
open and empty
block
closed
<default value>, false
write only
compilation error
Write
nil
block
open and non empty
block
open and empty
write value
closed
panic
receive only
compilation error
close
nil
panic
open and non empty
closes channel; reads suceed until channel is drained, then reads produce default value
open and empty
closes channel; reads produces default value
closed
panic
receive only
compilation error
Channel Owners&Consumers
A channel owner should:
instantiate the channel.
perform writes, or pass ownership to another goroutine.
close the channel.
encapsulate the previous three things in this list and expose them via a reader channel.
A channel consumer should:
knowing when a channel is closed.
be responsible for handling blocking for any reason.
Last updated
Was this helpful?