Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does runtime.LockOSThread allow child goroutines to run in same OS thread?

Tags:

go

I understand that in Go, runtime.LockOSThread() will bind a goroutine to one OS thread and not allow other goroutines to execute in that thread. Is this also true for child goroutines?

For example:

runtime.LockOSThread()
go func() {
    go func() {
        // Do something
    }()
    // Do something
}()

Do both of these goroutines execute in a single and exclusive OS thread or only the first one?

like image 440
joaonrb Avatar asked Jun 04 '15 14:06

joaonrb


People also ask

Are Goroutines the same as threads?

Threads are hardware dependent. Goroutines have easy communication medium known as channel. Thread does not have easy communication medium. Due to the presence of channel one goroutine can communicate with other goroutine with low latency.

What is runtime runtime package?

Package runtime contains operations that interact with Go's runtime system, such as functions to control goroutines. It also includes the low-level type information used by the reflect package; see reflect's documentation for the programmable interface to the run-time type system.

How do Goroutines work internally?

A goroutine has a simple model: it is a function executing concurrently with other goroutines in the same address space. It is lightweight, costing little more than the allocation of stack space. And the stacks start small, so they are cheap, and grow by allocating (and freeing) heap storage as required.

Why Goroutines are faster?

You create Goroutines to share data via channels. And because there is no need for exclusive access to global data structures, you gain speed.


2 Answers

The documentation for runtime.LockOSThread says:

LockOSThread wires the calling goroutine to its current operating system thread. Until the calling goroutine exits or calls UnlockOSThread, it will always execute in that thread, and no other goroutine can.

(emphasis mine)

This means that if a certain implementation of Go did what you're asking, it would be faulty.

To clarify: if a goroutine had reserved a thread and another goroutine executed on that same thread; that's what would be wrong.

like image 126
thwd Avatar answered Oct 18 '22 09:10

thwd


We can check it using pthread.h's pthread_self:

package main

// #include <pthread.h>
import "C"
import (
    "fmt"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    ch1 := make(chan bool)
    ch2 := make(chan bool)
    fmt.Println("main", C.pthread_self())
    go func() {
        runtime.LockOSThread()
        fmt.Println("locked", C.pthread_self())
        go func() {
            fmt.Println("locked child", C.pthread_self())
            ch1 <- true
        }()
        ch2 <- true
    }()
    <-ch1
    <-ch2
}

On my machine it prints something like this, main and locked always being sometimes the same, but sometimes different:

main 139711253194560
locked 139711219787520
locked child 139711236572928

EDIT I forgot about GOMAXPROCS. Added, the results are varying now.

like image 38
Ainar-G Avatar answered Oct 18 '22 11:10

Ainar-G