Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does goroutines behave on a multi-core processor

I am a newbie in Go language, so please excuse me if my question is very basic. I have written a very simple code:

func main(){
    var count int // Default 0

    cptr := &count

    go incr(cptr)

    time.Sleep(100)

    fmt.Println(*cptr)
}

// Increments the value of count through pointer var
func incr(cptr *int) {
    for i := 0; i < 1000; i++ {
            go func() {
                    fmt.Println(*cptr)
                    *cptr = *cptr + 1
            }()
      }
    }

The value of count should increment by one the number of times the loop runs. Consider the cases:

Loop runs for 100 times--> value of count is 100 (Which is correct as the loop runs 100 times).

Loop runs for >510 times --> Value of count is either 508 OR 510. This happens even if it is 100000.

I am running this on an 8 core processor machine.

like image 840
Nerve Avatar asked Jan 08 '14 10:01

Nerve


People also ask

Do Goroutines run on multiple cores?

The diagram shows that by using goroutines, your concurrent program is capable of running on a single CPU core, but as more CPU cores are added, more goroutines can be run in parallel to speed up the program. To get started with your new concurrent program, create a multifunc directory in the location of your choosing.

Are Goroutines multithreaded?

With Go, it's possible to do multi-threaded concurrency and parallelization with goroutines and goroutines work in an asynchronous way hence making use of both multi-threading and asynchronous programming efficiently.

What are Goroutines and how do they work?

GoRoutines are a Golang wrapper on top of threads and managed by Go runtime rather than the operating system. Go runtime has the responsibility to assign or withdraw memory resources from Goroutines. A Goroutine is much like a thread to accomplish multiple tasks, but consumes fewer resources than OS threads.

How does a multi-core CPU affect processing performance?

A multi-core processor has two or more cores (processing units). Each core handles different program instructions. This boosts the overall processing power. That's why a multi-core processor is faster than a single-core processor running at the same speed.


1 Answers

First of all: prior to Go 1.5 it runs on a single processor, only using multiple threads for blocking system calls. Unless you tell the runtime to use more processors by using GOMAXPROCS.

As of Go 1.5 GOMAXPROCS is set to the number of CPUS. See 6, 7 .

Also, the operation *cptr = *cptr + 1 is not guaranteed to be atomic. If you look carefully, it can be split up into 3 operations: fetch old value by dereferencing pointer, increment value, save value into pointer address.

The fact that you're getting 508/510 is due to some magic in the runtime and not defined to stay that way. More information on the behaviour of operations with concurrency can be found in the Go memory model.
You're probably getting the correct values for <510 started goroutines because any number below these are not (yet) getting interrupted.

Generally, what you're trying to do is neither recommendable in any language, nor the "Go" way to do concurrency. A very good example of using channels to synchronize is this code walk: Share Memory By Communicating (rather than communicating by sharing memory)

Here is a little example to show you what I mean: use a channel with a buffer of 1 to store the current number, fetch it from the channel when you need it, change it at will, then put it back for others to use.

like image 102
cfstras Avatar answered Sep 27 '22 19:09

cfstras