Go concurrent access to pointers methods

Issue

I’m trying to understand what happens when you make concurrent access to a pointers methods?

I have a map of pointers and spawn off a few go routines. I pass the map into each go routine and each go routine will use one of the values in the map. Nothing is being written to the map only being read from.

The map is small, only 4 keys so it’s possible that more than one go routine will be using the same value from the map.

Question is, what happens when two go routines call a method of the same pointer? Will I get unpredictable results?

EDIT

Example: I’m taking out the map portion as that’s not the question I’m after.

I have foo which is a pointer of type MyStruct and this structure has a method DoSomething that takes arguments. In the main function I’m creating two go routines and both of them make calls to foo.DoSomething passing different values. In this example the first go routine has a much larger calculation to preform than the second one (just using sleep times here to simulate calculations). Again nothing in the structure is changing I’m only making a call to the structures method. Do I have to worry about the second go routine making a call to foo.DoSomething when the first go routine is still working with the method?

package main

import (
    "log"
    "time"
)

type MyStruct struct {
}

func (self *MyStruct) DoSomething(value int) {

    log.Printf("%d Start", value)

    calculation_time := time.Duration(value) * time.Second
    log.Printf("%d Calculating", value, calculation_time)
    time.Sleep(calculation_time)

    log.Printf("%d Done", value)
}

func main() {

    var foo = new(MyStruct)

    go foo.DoSomething(5)

            // is this method call a problem when the first one is still working?
    go foo.DoSomething(2)

    time.Sleep(time.Duration(6 * time.Second))
}

Solution

Go methods have receivers. Receiver can be a pointer type. A method with the signature, for example:

func (r *R) foo(bar baz) // A method

is the same as

func foo(r *R, bar baz) // A plain old function

In other words, the receiver, pointer or not, is just an argument slot. Your question now reduces to:

What happens when two go routines call the above function with the same value of r?

A: It depends. Problem configurations:

  • foo is not re-entrant for any reason.
  • foo mutates *r (the pointee) w/o coordination/synchronization.
  • The last point is only a special case of: If foo mutates any shared state w/o coordination/synchronization: anything can happen.

If foo avoids the above tar pits then it is safe for being executed concurrently by multiple goroutines even with the same value of r.

Answered By – zzzz

Answer Checked By – Timothy Miller (GoLangFix Admin)

Leave a Reply

Your email address will not be published.