Friday, October 16, 2015

Concurrency Parallelism and Goroutines for Beginners

In the world around us many un/planned activities/events simultaneously and often independent of each other.  While reading this, you may receive a phone call and while still on the call you might receive  a few push notifications on your mobile from Facebook or WhatsApp. While reading this and attending to that phone call, you might be listening to your favorite number played in your home theater and you may reach out to adjust the volume level. Does this make sense or you're still scratching your head... yet another activity! 

Yes, the world is indeed parallel. Apart from everything else even in technology world also the concept of parallelism can be observed viz. Multicore machines, networks, clouds of CPUs, Users request to a web server - all are parallel.

That's probably the reason we get stuck at times when we try to solve a real world problem using the non parallel approach (read Object Oriented techniques).

Almost a decade back the following was one of the pet interview questions thrown mostly to any developer with 3+ years of experience:
  •  Have you implemented multi-threading in x language? 
Where x = C#, Java or any other language that supports multi-threading.

Without any doubt, I agree (like most of us) that multi-threading is complex and a beast too big to be tamed by mere mortals with average intelligence. You can agree to disagree with me and may call this a common fallacy :-)
  • Goroutines has made concurrency / multi-threading easier to use.
If you already understand the basics move on to Go Channels

What is Concurrency?

Concurrent = happening, or done at the same time

Concurrency is a way to structure a program by breaking it into pieces that can be executed independently.

The Go tools of concurrency make it almost trivial to build a safe, working, scalable & parallel design.

Here, Processes in the general sense, not Windows/Linux processes.

Is Concurrency same as Parallelism?

No. They are not same, but are related.

Rob Pike says:
  • Concurrency is about dealing with lots of things at once.
  • Parallelism is about doing lots of things at once.
  • Concurrency is about structure, parallelism is about execution.
  • Concurrency provides a way to structure a solution to solve a problem that may (but not necessarily) be parallelizable.
Here's an excellent video by none other than one of the creators of Go - Rob Pike Concurrency Is Not Parallelism

Go tools to Implement Concurrency
  • Goroutines - concurrent execution.
  • Channels - synchronization and messaging.
  • Select - multi-way concurrent control.
What is Goroutine?

A goroutine is a function running independently in the same address space as other goroutines. They're a bit like threads, but they're much cheaper.

A goroutine is a lightweight thread of execution. It's routine to create thousands of goroutines in one program. Stacks start small, but grow and shrink as required.
Goroutines aren't free, but they're very cheap.

Important Update: To synchronize concurrently running functions Go provides Channels.

The following code sample uses time.Sleep() to sync the goroutines - bad programming practice and should be avoided. Synchronizing your goroutines like this can introduce several serious bugs in your code. The purpose of this code sample is to give you a feel of goroutines in action.

Example Code

Play with the code


package main

import (
 "fmt"
 "time"
)

func Tortoise() {

 time.Sleep(5 * 1e9)
 fmt.Println("Tortoise is still somewhere near the Starting Line.")
 time.Sleep(10 * 1e9)
 fmt.Println("Tortoise reaches 10 miles after 10 sec.")
 time.Sleep(10 * 1e9)
 fmt.Println("Tortoise reaches 20 miles after 20 sec.")
 time.Sleep(6 * 1e9)
 fmt.Println("Surprise... Tortoise reaches finish line! Completes 26 miles in 26 sec")
}

func Rabbit() {
time.Sleep(2 * 1e9)
 fmt.Println("Rabbit reaches 10 miles after 2 sec.")
 time.Sleep(4 * 1e9)
 fmt.Println("Rabbit reaches 20 miles after 4 sec.")
 time.Sleep(7 * 1e9)
 fmt.Println("Rabbit takes power nap.")
 time.Sleep(20 * 1e9)
 fmt.Println("Rabbit reaches the finishing line! OOOPs Rabbit lost the race!")
}

func main() {

 fmt.Println("Marathon Race - 26 miles, Tortoise vs. Rabbit.")
 fmt.Println("On your mark. Starting pistol fired...")
 fmt.Println("The Rabbit sprints ahead while the Tortoise is dead slow.")
 go Rabbit()
 go Tortoise()
 time.Sleep(34 * 1e9)
 fmt.Println("Keep GO-ing :-) even if you're slow.")
}


Output

Marathon Race - 26 miles, Tortoise vs. Rabbit.
On your mark. Starting pistol fired...
The Rabbit sprints ahead while the Tortoise is dead slow.
Rabbit reaches 10 miles after 2 sec.
Tortoise is still somewhere near the Starting Line.
Rabbit reaches 20 miles after 4 sec.
Rabbit takes power nap.
Tortoise reaches 10 miles after 10 sec.
Tortoise reaches 20 miles after 20 sec.
Surprise... Tortoise reaches finish line! Completes 26 miles in 26 sec
Rabbit reaches the finishing line! OOOPs Rabbit lost the race!
Keep GO-ing :-) even if you're slow

A Brief Description of Above Code

time.Sleep(5 * 1e9)


In above code we're introducing a time delay of 5 seconds. Replace 5 with 10 to get a delay of 10 seconds. Know more about Sleep function here.

Apart from the main() function there are other 2 functions namely Tortoise() and Rabbit().

In the main() function we've 2 goroutines namely go Rabbit() and go Tortoise().
From the output you can easily see how both the functions are getting executed concurrently.

Important: By default, Go code is NOT parallel i.e. only a single core or processor is dedicated to a Go-program, regardless of how many goroutines are started in it; so these goroutines are running concurrent, they are not running in parallel: only one goroutine is running at a time.


How can I improve this code? Please share your thoughts.

Monday, October 5, 2015

Go Interfaces for Absolute Beginners

The concept of Interfaces and its practical implementation may be rather daunting for beginners. It may require immense time and patience to assimilate the idea of interfaces.

Interfaces are an abstraction that helps you to achieve the following objectives with your code:

                  1. Clean & readable.
                  2. Scalable.

An interface defines a set of methods without any implementation code. So, an interface is simply an abstraction and can't contain any variables or code.


Declaration format of interfaces:

type Logger interface {
            method1 (param list) return type
            method1 (param list) return type
}

As per the official recommendation:
  • In the above format, Logger is the name of interface. It is idiomatic in Go to suffix the name of interface with er in most of the cases. There are exceptions but a common practice for naming an interface is: 
        • method name + er
  • Interfaces with one or two methods are common in Go code. More than three methods in an Interface is not considered idiomatic.
  • A type can implement multiple interfaces. Interface can be implemented by any type. But an interface can't implement itself.
  • Multiple types can implement the same interface.
  • Like many other languages, in Go also, we must implement all the methods in the interface.


Here's a code snippet (Code Ref# 1) that finds the area of a rectangle and triangle using functions. The same exercise is refactored in Code Ref#2 using structsmethods and interfaces.

Code Ref# 1. Play Here


package main

import "fmt"

func AreaRectangle(l, w int) int {

 return l * w
}

func AreaTriangle(b, h int) int {

 return (b * h) / 2 //Area of a triangle is (base*height)/2
}

func main() {

 fmt.Println("Area of Rectangle:", AreaRectangle(3, 4))
 fmt.Println("Area of Triangle:", AreaTriangle(5, 20))

}

Output

Area of Rectangle: 12
Area of Triangle: 50

Code Ref# 2. Play Here

package main

import "fmt"

type Rectangle struct {
 width, height int
}

type Triangle struct {
 base, height int
}
type Shaper interface {
 Area() int
}
// You must implement all the methods in the interface
func (s Rectangle) Area() int {
 return s.width * s.height
}
func (t Triangle) Area() int {
 return (t.base * t.height) / 2
}
// Variable declared as an interface type can call methods that are in the named interface.
// Generic 'measure' function that works on any Shape.

func measure(s Shaper) {
 fmt.Println(s)
 fmt.Println(s.Area())
}
func main() {
 s := Rectangle{width: 3, height: 4}
 t := Triangle{base: 5, height: 20}
// The Rectangle struct type implements the 'Shaper' interface so we can use instances 
// of these structs as arguments to measure.
 measure(s)
 measure(t)
}



Output



{3 4}
12
{5 20}
50
P.S. Interfaces are a bit difficult to understand. A beginner must persist with it, practice as many examples as possible to understand and assimilate the concept. I'll review this post every now and then and may add a few more code samples.