简体   繁体   中英

Why does a goroutine have no identity

I new to golang and I am reading the example from the book gopl.

Section 9.8.4 of The Go Programming Language book explains why Goroutines have no notion of identity that is accessible to the programmer

Goroutines have no notion of identity that is accessible to the programmer. This is by design, since thread-local storage tends to be abused. For example, in a web server implemented in a language with thread-local storage, it's common for many functions to find information about the HTTP request on whose behalf they are currently working by looking in that storage. However, just as with programs that rely excessively on global variables, this can lead to an unhealthy ''action at a distance'' in which the behavior of a function is not determined by its arguments alone, but by the identity of the thread in which it runs. Consequently, if the identity of the thread should change—some worker threads are enlisted to help, say—the function misbehaves mysteriously.

and use the example of web server to illustrate this point. However, I have difficulty in understanding why the so called "action at a distance" is a bad practice and how this leads to

a function is not determined by its arguments alone, but by the identity of the thread in which it runs.

could anyone give an explanation for this(preferably in short code snippets)

Any help is appreciated

Let's say we have the following code:

func doubler(num int) { 
    return num + num
}

doubler(5) will return 10 . go doubler(5) will also return 10 .

You can do the same with some sort of thread-local storage, if you want:

func doubler() { 
    return getThreadLocal("num") + getThreadLocal("num")
}

And we could run this with something like:

go func() {
    setThreadLocal("num", 10)
    doubler()
}()

But which is clearer? The variant which explicitly passes the num argument, or the variant which "magically" gets this from sort of thread-local storage?

This is what is meant with "action at a distance". The line setThreadLocal("num", 10) (which is distant) affects how doubler() behaves.


This example is clearly artificial, but the same principle applies with more real examples. For example, in some environments it's not uncommon to use thread-local store things such as user information, or other "global" variables.

This is why the paragraph you quoted compared it to global variables: thread-local storage are global variables, applicable only to the current thread.

When you passing parameters as arguments things are a lot clearer defined. There is no magic (often undocumented) global state that you need to think of when debugging things or writing tests.

See my repo

package main

import (
    "fmt"
    "time"

    "github.com/timandy/routine"
)

func main() {
    goid := routine.Goid()
    fmt.Printf("cur goid: %v\n", goid)
    go func() {
        goid := routine.Goid()
        fmt.Printf("sub goid: %v\n", goid)
    }()

    // Wait for the sub-coroutine to finish executing.
    time.Sleep(time.Second)
}

I recommend looking at this post for an example of why someone might want to get information about the current thread/thread a function is running in: stackoverflow - main threads in C#

As pointed out in the question, conditioning the behavior of a function on certain thread requirements (most likely) produces fragile/error-prone code that is difficult to debug.

I guess what your text book is trying to say is that a function should never rely on running in a specific thread, look up threads, etc. because this can cause unexpected behavior (especially in an API, if it's not obvious to the end-user that a function has to run in a specific thread). In Go, anything like that is impossible purely by language design. The behavior of a goroutine never depends on threads or something similar just because goroutines don't have an identity as you say correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM