V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
chaleaochexist
V2EX  ›  Go 编程语言

golang 是单进程的吗?

  •  1
     
  •   chaleaochexist · 193 天前 · 5452 次点击
    这是一个创建于 193 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在一个 goroutine 修改环境变量, 想在其他所有 goroutine 中生效? 可以吗?

    第 1 条附言  ·  192 天前
    这个帖子 我不会再回复了.
    我建议你们也不要回帖了, 虽然我已经下沉了 10 天.

    B 了一些人.

    将来有问题还是会在本站发帖咨询的, 因为没有找到更好的论坛.
    xhatt
        1
    xhatt  
       193 天前
    试一下不就知道了?很简单
    chaleaochexist
        2
    chaleaochexist  
    OP
       193 天前
    @xhatt 我试过了 是的.
    但是我无法保证一定是.

    不知道我说没说清楚.
    qloog
        3
    qloog  
       193 天前   ❤️ 1
    Golang 默认是单进程的,这与其他语言如 Java 、Node.js 有所不同。
    原因有以下几点:
    1. Goroutine 更轻量,一个进程可以同时运行成千上万个 Goroutine,所以不需要多进程。
    2. Goroutine 有运行时(Runtime)调度和上下文切换,不需要进程或线程切换的开销。
    3. 共享内存通信更简单快捷,不需要跨进程通信。
    4. 不需要考虑锁、线程安全问题,编程模型更简单。
    5. GC 更容易实现且高效。
    但是 Golang 也可以通过 os.Exec 启动新进程,或者在不同端口监听启动多个进程。
    结论:
    - Golang 默认单进程,这由语言设计决定。
    - 单进程可以处理更高并发,编程模型更简单。
    - 也可以手动启动多进程满足特定需求。

    所以 Golang 作为一种现代编程语言,单进程多 Goroutine 是更合理的选择。但也保留了启动多进程的能力。
    thinkershare
        4
    thinkershare  
       193 天前   ❤️ 1
    Golang? 你确认没问错? 线程 or 进程?
    emSaVya
        5
    emSaVya  
       193 天前   ❤️ 3
    这几条回答也是够逆天了 single/multi process 什么时候跟编程语言绑定了?
    dode
        6
    dode  
       193 天前
    goroutine 连线程都不是独立的
    standchan
        7
    standchan  
       193 天前   ❤️ 1
    这个问题,都不知道该怎么开口回答。。。。
    dode
        8
    dode  
       193 天前   ❤️ 1
    @emSaVya 一般来说,python 是单线程的
    lincanbin
        9
    lincanbin  
       193 天前   ❤️ 2
    一个编译型语言哪来的单进程/多进程,那不取决于你代码是单进程/多进程吗?
    62742a40
        10
    62742a40  
       193 天前
    我实在不知道这个问题是怎么产生的
    Ericcccccccc
        11
    Ericcccccccc  
       193 天前
    标题和内容完全不搭啊...

    回到你的问题, 实时修改环境变量能不能生效得看这个值是啥时候读的.
    mightybruce
        12
    mightybruce  
       193 天前   ❤️ 1
    我建议赶紧转行吧。
    weiwenhao
        13
    weiwenhao  
       193 天前
    多开几个 goroutine, ps 看一下就知道 golang 开了几个进程啦。如果想看线程就 ps -T 看一下线程数。
    kkk9
        14
    kkk9  
       193 天前
    OP 是想问全局变量和局部变量的区别吗?
    leonshaw
        15
    leonshaw  
       193 天前   ❤️ 2
    没见过哪个语言会偷偷开进程
    fregie
        16
    fregie  
       193 天前 via Android
    确实,这个问题我都不知道该怎么回答了....
    我觉得你是想问这个:不同 goroutine 中其中一个修改了环境变量,其他的过去到的值有的是改之后的有的是改之前的。
    我觉得你是没控制好获取的时机,估计有些在修改生效前就获取了
    bug123
        17
    bug123  
       193 天前   ❤️ 6
    知道的和不知道的都懵逼了
    des
        18
    des  
       193 天前
    @emSaVya 很明显三楼内容是 GPT 生成的
    ysc3839
        19
    ysc3839  
       193 天前 via Android   ❤️ 1
    goroutine 是单进程多线程
    4kingRAS
        20
    4kingRAS  
       193 天前
    看 pid 就知道了,windows 也有 pid
    dw2693734d
        21
    dw2693734d  
       193 天前
    哪个语言是多进程的?
    wangritian
        22
    wangritian  
       193 天前
    你有这个疑问是不是从 php-fpm 转过来的
    可以这么回答,如果你没主动开进程,那它就是单进程
    smallyu
        23
    smallyu  
       193 天前
    单进程会占用多个 CPU 吗?
    emSaVya
        24
    emSaVya  
       193 天前
    @dode

    没有任何编程语言阻挡你选择并发模型, 最多是有个 best practice 。

    python 开发者也可以写 multi thread 的代码, 只不过 GIL 存在 multi thread 不起作用而已, 而且 GIL 不是编程语言的限制 是 runtime 的限制 换一个编译器即可。
    wtfedc
        25
    wtfedc  
       193 天前
    Go (也称为 Golang) 是一种编程语言,它本身并不决定程序的多进程或单进程性质。Go 语言提供了并发编程的强大工具,例如 goroutine 和通道,以支持多线程和并发编程。这意味着你可以在 Go 中轻松地创建多个并发的执行线程,而不必自己管理底层的线程或进程。

    Go 程序通常是单进程的,但这个进程可以包含多个并发的 goroutine ,这些 goroutine 可以并行执行任务。这种设计使 Go 程序在处理高并发性能方面非常出色。

    虽然 Go 本身不决定程序是单进程还是多进程,但开发人员可以在 Go 中使用并发编程来构建多进程应用程序,如果需要的话。例如,你可以编写一个 Go 程序,该程序启动多个进程,每个进程运行不同的任务,并且这些进程可以通过通道进行通信。

    总之,Go 语言本身不限制进程的数量,但提供了丰富的并发编程工具,使开发人员能够有效地管理多个并发执行线程。

    from chatGPT
    moonsn
        26
    moonsn  
       193 天前 via iPhone
    看 setenv 和 getenv 的源码就知道了,有锁。还是包级别的锁。结论:多个 goroutine 并发使用是安全的。
    chaleaochexist
        27
    chaleaochexist  
    OP
       193 天前
    @thinkershare 我当然知道是多线程了.
    我的问题是是否是单进程 因为环境变量的设置默认只对当前进程有效.
    chaleaochexist
        28
    chaleaochexist  
    OP
       193 天前
    @emSaVya 那我换个问法 go runtime 是单进程的吗?
    importlau
        29
    importlau  
       193 天前
    @chaleaochexist 进程之间资源是隔离的
    chaleaochexist
        30
    chaleaochexist  
    OP
       193 天前
    @emSaVya
    @dode
    @standchan
    @lincanbin
    @62742a40
    @Ericcccccccc
    @mightybruce
    @kkk9
    @leonshaw
    @fregie
    @bug123

    @ysc3839
    @dw2693734d
    @wangritian
    @smallyu
    @emSaVya
    @wtfedc
    @moonsn

    好吧我换个问法, 当一个 go 程序运行的时候, 当我不主动调用 os.fork os.exec 之类 (希望这里不要说我忘记加括号了)
    多 goroutine 是否在同一个进程下.
    因为我有一个定时任务, 会 定期修改环境变量 同时要求其他 goroutine 实时读取这个环境变量.

    @错了的花, 见谅.
    chaleaochexist
        31
    chaleaochexist  
    OP
       193 天前
    @importlau 不知道你是针对几楼的回复 说 进程之间资源隔离的问题.

    我知道进程之间是隔离的.

    所以我想知道 multiple goroutine 是否是运行在同一个进程下.
    pkoukk
        32
    pkoukk  
       193 天前   ❤️ 1
    我见识少,有什么语言的多线程是通过多进程实现的嘛?
    ysc3839
        33
    ysc3839  
       193 天前 via Android
    @chaleaochexist 26 楼已经回答了,没问题
    chaleaochexist
        34
    chaleaochexist  
    OP
       193 天前
    @smallyu
    单进程会占用多个 CPU 吗?
    会的.
    chaleaochexist
        35
    chaleaochexist  
    OP
       193 天前
    @dw2693734d
    我不知道啊 我知道 python runtime 是单进程的.

    我还知道 golang 是多线程模型, 但是不确实是不是单进程的 所以来问问啊.
    importlau
        36
    importlau  
       193 天前
    @chaleaochexist 是的, 同一个进程下的。
    ysc3839
        37
    ysc3839  
       193 天前 via Android
    @pkoukk 用户模式线程或者说协程不能用多进程来实现,但是一些子逻辑是可以用多进程的。
    因为 Unix 有 fork 可以很方便地保留数据启动新进程,有些程序的子逻辑(比如处理客户端的请求)就会 fork 一下再处理。
    chaleaochexist
        38
    chaleaochexist  
    OP
       193 天前
    @62742a40 我实在不知道这个问题是怎么产生的

    环境变量的修改只在当前进程生效
    我在一个 goroutine 修改环境变量, 想在其他所有 goroutine 中生效? 可以吗?
    chaleaochexist
        39
    chaleaochexist  
    OP
       193 天前
    @Ericcccccccc
    标题和内容完全不搭啊...
    回到你的问题, 实时修改环境变量能不能生效得看这个值是啥时候读的.

    假设两个 goroutine 一个随机写 一个随机读
    要求每次都读到最新的环境变量.

    如果这两个 goroutine 在两个进程下. 默认是不行的.
    proxytoworld
        40
    proxytoworld  
       193 天前
    @chaleaochexist 同一个进程 环境变量是一份的
    mightybruce
        41
    mightybruce  
       193 天前
    多个 goroutine 并不对应多进程,除非你通过 syscall 在代码主动去创建进程。
    你改了环境变量,其他 goroutine 是感知不到的, 除非再次主动去读。
    多个 goroutine 在一个进程中。
    e7
        42
    e7  
       193 天前
    以前找工作的时候经常遇到面试官问类似这种问题,一脸懵逼
    awalkingman
        43
    awalkingman  
       193 天前
    你是不是想问不同 goroutine 之间的通信机制?
    bler
        44
    bler  
       193 天前   ❤️ 1
    我大概明白楼主是啥意思,楼主应该是想问,main1.go 和 main2.go 独立运行,会不会被 go 语言分配到同一个进程之中。我被 python 的 scrapy 框架坑过,scrapy crawl 命令运行爬虫的时候,scrapy crawl spider1 和 scrapy crawl spider2 是运行在同一个进程之下的,pipeline 的类变量在两个爬虫中会共用,估计楼主应该是遇到类似的问题了
    xdeng
        45
    xdeng  
       193 天前
    单进程是常态吧
    xsen
        46
    xsen  
       193 天前
    @chaleaochexist #39 关键字:资源并发访问
    不同进程,系统也有机制可以多进程同步
    不同线程,线程同步
    不同协程,对于 go 来说就是加锁如 mutex
    Immortan
        47
    Immortan  
       193 天前   ❤️ 2
    - Golang 不是单进程的,GOMAXPROCS 默认等于运行时机器的 runtime.NumCPU()
    - 但是开发者不用关心,这是 OS 层面的抽象,OS 会保证即使实际运行在多核上,其行为也和运行在单核上一样,比如环境变量的变化。
    - 环境变量是 OS 管理的,读取、修改环境变量都需要通过系统调用进入内核态,自然会在所有 goroutine 中生效。
    - 一般非常少会通过环境变量的运行时改变来控制代码行为,尤其像 Golang 这种原生对并发支持力度就很大的语言。如上所述,环境变量的读取需要通过系统调用,某种程度上是个"很贵"的操作。
    jdkxnktkdkxod
        48
    jdkxnktkdkxod  
       193 天前
    这个问题槽点太多,不知道该怎么回答
    LindsayZhou
        49
    LindsayZhou  
       193 天前   ❤️ 1
    是不是可以这样想,goroutine 之间是可以共享全局变量的,那么表示所有的 goroutine 是共用一套内存地址空间的。

    而环境变量存储的位置,如果我没记错,是在程序入口前面一小段的内存里面,既然所有的内存空间是共享的,那么这段环境变量的内存也是共享的。

    这样就摆脱了线程进程的概念,不用考虑那些了。

    (如果是进程,那内存页就是 COW 了)
    ygtq
        50
    ygtq  
       193 天前
    @chaleaochexist 多 goroutine 是否在同一个进程下? 我的理解是,肯定在。因为你没有主动 fork ,golang 也不会主动多开一个进程,go 只是一个静态编程语言,换言之你用 c/c++写,编译生成可执行程序,代码不主动开进程,语言不会开的啊
    kiripeng
        51
    kiripeng  
       193 天前
    Happens-Before 原则
    EspoirBao
        52
    EspoirBao  
       193 天前
    看到单进程的时候突然小脑猥琐了一下,在想是什么情况下需要改多进程的环境变量,进程一般都属于 OS 级别控制的吧???
    zmaplex
        53
    zmaplex  
       193 天前 via Android
    不管什么语言,只要不 fork 就是天王老子来了都是单进程。要多进程,只要不主动加锁限制,都可以多进程运行(系统限制除外)
    standchan
        54
    standchan  
       193 天前
    你没 exec 操作,goroutine 就是一定是单进程,然后 goroutine 是在语言层面复用 os 的线程。此外,我写了 demo 代码,结果是其他 goroutine 也可以读到新修改的环境变量,前提的实时去读。
    RedisMasterNode
        55
    RedisMasterNode  
       193 天前
    @dw2693734d 楼主问这个问题肯定是有他背景,例如 Python 进程经常用 Gunicorn 或者 uwsgi 托管,这些都会导致应用程序以多个进程形式运行。

    我觉得大家回答不用太过抠字眼了...其实就是个快问快答,但是较真(较真不代表不好)的人很多,才搞得帖子这样...

    包括一些什么可以 os.Exec 扩展多进程,拜托,别的语言一样可以,补充这种信息对回答问题一点帮助都没有,不如直接点明 Go 和其他语言的区别在哪里简洁明了。
    ding2dong
        56
    ding2dong  
       193 天前
    当然可以啊,goroutine 是线程不是进程
    aisk
        57
    aisk  
       193 天前
    @RedisMasterNode 他背景他说了,一个 goroutine 里设置环境变量另外一个读不到,然后不怀疑自己代码有 bug ,怀疑 go 是多进程运行不同 goroutine 。
    chaleaochexist
        58
    chaleaochexist  
    OP
       193 天前
    @aisk 不是怀疑 我还没开始写呢.
    提前做点调查.
    chaleaochexist
        59
    chaleaochexist  
    OP
       193 天前
    @standchan 这个东西不能通过 demo 去验证.
    当然了严谨一点说 可以证伪. 但是不能验证正确.

    譬如 runtime 有一种机制, 当 goroutine < 5. 或者换个说法 count(runtime) < 5 是单进程, >=5 是多进程模式.
    所以我发帖上来问问, 不知道为什么楼上一堆冷嘲热讽.
    chaleaochexist
        60
    chaleaochexist  
    OP
       193 天前
    @standchan
    count(runtime) < 5
    -->
    count(goroutine) < 5
    chaleaochexist
        61
    chaleaochexist  
    OP
       193 天前
    @kiripeng 大佬这是另一个问题了.
    大佬能通俗易懂的解释一下 什么是 Happens-Before 吗?
    chaleaochexist
        62
    chaleaochexist  
    OP
       193 天前
    @ygtq go 和 c++的区别是 go 有一个 goroutine 这个东西是由 runtime 控制的. 所以才上来确认一下.
    通常来说确实应该是单进程.
    aisk
        63
    aisk  
       193 天前
    @chaleaochexist 动手测试一分钟,群里讨论一整天。
    chaleaochexist
        64
    chaleaochexist  
    OP
       193 天前
    @aisk 这个东西不能通过 demo 去验证.
    当然了严谨一点说 可以证伪. 但是不能验证正确.

    譬如 runtime 有一种机制, 当 goroutine < 5. 或者换个说法 count(runtime) < 5 是单进程, >=5 是多进程模式.
    所以我发帖上来问问, 不知道为什么楼上一堆冷嘲热讽.
    standchan
        65
    standchan  
       193 天前
    我没有找到你说的 golang runtime 当协程数量大于一定数目就变成了多进程模式。你在哪里看到的资料能发出来看一下吗?我认为多进程肯定不合理,进程之间的通信要比协程之间的通信复杂太多了,还涉及到了各种同步等等乱七八糟的。另外,你起初问的问题确实特别让人费解,标题和正文我找不到逻辑的相关性
    standchan
        66
    standchan  
       193 天前
    另外 runtime 对 goroutine 的控制也是基于系统进程里面进行的。它是在进程下面的,当然 exec 会生成新的进程,但生成的进程和 golang 程序所在的进程完全没关系。runtime 也不可能凌驾于进程们之上去管理多个进程。go 是面向云原生高并发,如果是你说的多进程模式,那延迟会高很多很多。
    aisk
        67
    aisk  
       193 天前
    @chaleaochexist 错的不是你。
    chaleaochexist
        68
    chaleaochexist  
    OP
       193 天前
    @standchan 当协程数量大于一定数目就变成了多进程模式.
    这个是我脑补的.

    我其实也倾向于是单进程.

    只不过上来发帖确认一下.
    standchan
        69
    standchan  
       193 天前
    @chaleaochexist #68 嗯嗯,那现在应该知道结果了就行了。另外,问题的描述可以再提升一下,看起来真的会让人有点懵。
    voidmnwzp
        70
    voidmnwzp  
       193 天前
    …你告我哪个语言不是单进程的
    qwq11
        71
    qwq11  
       193 天前 via Android
    op 去看下操作系统,环境变量是在进程启动的时候被 OS 压到程序的栈里的,所以说是静态的,而不是动态读取。如果你说的是在同一进程下的 goroutine ,显然不会生效,如果你说的是不同进程的 goroutine ,并且在修改完了之后才启动新进程,那答案是会生效

    你在 #30 说的情况,答案是不会生效
    chaleaochexist
        72
    chaleaochexist  
    OP
       193 天前
    @qwq11 啊??
    什么?
    ```
    package main

    import (
    "fmt"
    "os"
    "time"
    )

    func main() {
    os.Setenv("FOO", "1")
    fmt.Println(os.Getenv("FOO"))
    go func() {
    os.Setenv("FOO", "2")
    }()
    time.Sleep(1 * time.Second)
    fmt.Println(os.Getenv("FOO"))
    }
    ```
    CrazyMonkeyV
        73
    CrazyMonkeyV  
       192 天前
    @chaleaochexist 前面我觉得你菜就算了,谁没菜过?看到后面有点逆天。程序员不是自己搞 demo 来证明,靠不明需求的论坛? 6666
    Masoud2023
        74
    Masoud2023  
       192 天前
    @chaleaochexist #72

    好奇你以前是做什么语言的。这种拿环境变量共享内存的方法我还是第一次见到。

    go 的话共享内存应该用 channel ?
    bler
        75
    bler  
       192 天前
    @bler 我更新一下我的回答,”pipeline 的类变量在两个爬虫中会共用“,这是错误的,虽然两个爬虫在同一进程中,但是两个爬虫类变量是隔离的
    chaleaochexist
        76
    chaleaochexist  
    OP
       192 天前
    @Masoud2023 因为我 B 了一些人不知道你说的 72 楼是哪个.

    也不算共享内存吧.
    就是在不停机的情况下 动态切换 kafka 的配置.
    且 if flag == 1 then 从环境变量读配置
    else 从数据库读配置.

    那我之前的想法是当从数据库读配置之后, 写到环境变量中, 这样其他代码就不用动了.
    然后就发帖问问题了.

    说得通吗?
    pkoukk
        77
    pkoukk  
       192 天前
    @chaleaochexist #76
    有这种需求,一般我们会搞个 etcd ,redis 也行啊。
    你这个玩法让人真是搞不懂,线上部署的时候直接跑二进制,不用 docker ?
    不用 docker 隔离环境罢了,还用环境变量,这么信任跑在这台机器上的其它服务?
    说到进程问题,我用过的语言里,只要你不 fork ,它们就是共用完全相同的上下文和内存,别管他在 cpu 里有几个实例,那是 os 的事情,和语言无关。
    qwq11
        78
    qwq11  
       192 天前
    @chaleaochexist #72 你是对的,去研究了下 linux 确实可以修改本进程的环境变量,修改之后 OS 会重新给进程分配环境变量表,这点有点出乎意料
    #76 的需求建议用变量存,把 os.Getenv 换成 KafkaConfigProvisioner.GetConfig 也用不了多少时间,比你发帖回帖快,用环境变量还得上信号量或者读写锁
    chaleaochexist
        79
    chaleaochexist  
    OP
       192 天前
    @pkoukk
    你说的是类似 zookeeper 的监听与推送吧?

    是 docker 里的环境变量. 为什么提到环境变量就一定是裸机的呢? docker 不能有环境变量吗?
    无论是推还是拉 都需要网络开销. 本地读取环境变量对于小项目来说就是最佳方式. 搞那么做组件做什么?

    不知道是谁的问题, 这个楼里全都是反问和嘲讽. 不知道是我的问题还是怎么回事.
    ==========================================
    以下我想回复你的第一个版本.
    @pkoukk

    是 docker 里的环境变量.

    你说的是类似 zookeeper 的监听与推送吧?

    小项目 一开始设计的时候就没那么复杂.
    chaleaochexist
        80
    chaleaochexist  
    OP
       192 天前
    @qwq11 是的.我最后是用 viper 解决的.
    实际上, 我发帖的时候, 问题已经解决了.

    这就是一个很单纯的问题. 也许在很多人看来很 SB.
    但是我现在是有点困惑为什么一开始嘲讽的人那么多.
    tonghuashuai
        81
    tonghuashuai  
       192 天前
    跟 GOMAXPROCS 有关吧,GOMAXPROCS 默认为 CPU 核心数,GOMAXPROCS 参数来确定线程数。
    然后 Go 运行时调度使用 m:n 策略,复用 m 个 goroutine 到 n 个线程。
    chaleaochexist
        82
    chaleaochexist  
    OP
       192 天前
    @qwq11 还有就是其实不需要信号量和读写锁. 这个和我的具体业务有关. 具体就不展开讲了.
    Jooeeee
        83
    Jooeeee  
       192 天前
    语言跟操作系统是两码事儿,进程分为线程,线程使用一小块内存构造 goroutine ,由于进程的所有现成共享内存,因此 goroutine 可以在不同的线程上跑。golang 可以在 goroutine 中启动新的进程
    mightybruce
        84
    mightybruce  
       192 天前
    你选择用环境变量实现,可以说是非常差的方式, 有非常多的方式可以实现
    1. 服务通过读取一些第三方配置中心来动态改变,比如 etcd, nacos
    2. 服务中直接写一个 http 控制服务,接受请求直接切换。
    dyllen
        85
    dyllen  
       179 天前   ❤️ 1
    单进程多线程,编译一个 exe 出来,只有一个进程,系统线程默认是和 cpu 核数是相等的,一个 goroutine 的执行是在线程里面执行的,不一定是哪个线程。go 的 goroutine 是共享内存的,一个全局变量可以多个 goroutine 修改和读取,会互相影响。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1087 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 23:12 · PVG 07:12 · LAX 16:12 · JFK 19:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.