我在一个 goroutine 修改环境变量, 想在其他所有 goroutine 中生效? 可以吗?
1
xhatt 350 天前
试一下不就知道了?很简单
|
2
chaleaochexist OP |
3
qloog 350 天前 1
Golang 默认是单进程的,这与其他语言如 Java 、Node.js 有所不同。
原因有以下几点: 1. Goroutine 更轻量,一个进程可以同时运行成千上万个 Goroutine,所以不需要多进程。 2. Goroutine 有运行时(Runtime)调度和上下文切换,不需要进程或线程切换的开销。 3. 共享内存通信更简单快捷,不需要跨进程通信。 4. 不需要考虑锁、线程安全问题,编程模型更简单。 5. GC 更容易实现且高效。 但是 Golang 也可以通过 os.Exec 启动新进程,或者在不同端口监听启动多个进程。 结论: - Golang 默认单进程,这由语言设计决定。 - 单进程可以处理更高并发,编程模型更简单。 - 也可以手动启动多进程满足特定需求。 所以 Golang 作为一种现代编程语言,单进程多 Goroutine 是更合理的选择。但也保留了启动多进程的能力。 |
4
thinkershare 350 天前 1
Golang? 你确认没问错? 线程 or 进程?
|
5
emSaVya 350 天前 3
这几条回答也是够逆天了 single/multi process 什么时候跟编程语言绑定了?
|
6
dode 350 天前
goroutine 连线程都不是独立的
|
7
standchan 350 天前 1
这个问题,都不知道该怎么开口回答。。。。
|
9
lincanbin 350 天前 2
一个编译型语言哪来的单进程/多进程,那不取决于你代码是单进程/多进程吗?
|
10
62742a40 350 天前
我实在不知道这个问题是怎么产生的
|
11
Ericcccccccc 350 天前
标题和内容完全不搭啊...
回到你的问题, 实时修改环境变量能不能生效得看这个值是啥时候读的. |
12
mightybruce 350 天前 1
我建议赶紧转行吧。
|
13
weiwenhao 350 天前
多开几个 goroutine, ps 看一下就知道 golang 开了几个进程啦。如果想看线程就 ps -T 看一下线程数。
|
14
kkk9 350 天前
OP 是想问全局变量和局部变量的区别吗?
|
15
leonshaw 350 天前 2
没见过哪个语言会偷偷开进程
|
16
fregie 350 天前 via Android
确实,这个问题我都不知道该怎么回答了....
我觉得你是想问这个:不同 goroutine 中其中一个修改了环境变量,其他的过去到的值有的是改之后的有的是改之前的。 我觉得你是没控制好获取的时机,估计有些在修改生效前就获取了 |
17
bug123 350 天前 6
知道的和不知道的都懵逼了
|
19
ysc3839 350 天前 via Android 1
goroutine 是单进程多线程
|
20
4kingRAS 350 天前
看 pid 就知道了,windows 也有 pid
|
21
dw2693734d 350 天前
哪个语言是多进程的?
|
22
wangritian 350 天前
你有这个疑问是不是从 php-fpm 转过来的
可以这么回答,如果你没主动开进程,那它就是单进程 |
23
smallyu 350 天前
单进程会占用多个 CPU 吗?
|
24
emSaVya 350 天前
@dode
没有任何编程语言阻挡你选择并发模型, 最多是有个 best practice 。 python 开发者也可以写 multi thread 的代码, 只不过 GIL 存在 multi thread 不起作用而已, 而且 GIL 不是编程语言的限制 是 runtime 的限制 换一个编译器即可。 |
25
wtfedc 350 天前
Go (也称为 Golang) 是一种编程语言,它本身并不决定程序的多进程或单进程性质。Go 语言提供了并发编程的强大工具,例如 goroutine 和通道,以支持多线程和并发编程。这意味着你可以在 Go 中轻松地创建多个并发的执行线程,而不必自己管理底层的线程或进程。
Go 程序通常是单进程的,但这个进程可以包含多个并发的 goroutine ,这些 goroutine 可以并行执行任务。这种设计使 Go 程序在处理高并发性能方面非常出色。 虽然 Go 本身不决定程序是单进程还是多进程,但开发人员可以在 Go 中使用并发编程来构建多进程应用程序,如果需要的话。例如,你可以编写一个 Go 程序,该程序启动多个进程,每个进程运行不同的任务,并且这些进程可以通过通道进行通信。 总之,Go 语言本身不限制进程的数量,但提供了丰富的并发编程工具,使开发人员能够有效地管理多个并发执行线程。 from chatGPT |
26
moonsn 350 天前 via iPhone
看 setenv 和 getenv 的源码就知道了,有锁。还是包级别的锁。结论:多个 goroutine 并发使用是安全的。
|
27
chaleaochexist OP @thinkershare 我当然知道是多线程了.
我的问题是是否是单进程 因为环境变量的设置默认只对当前进程有效. |
28
chaleaochexist OP @emSaVya 那我换个问法 go runtime 是单进程的吗?
|
29
importlau 350 天前
@chaleaochexist 进程之间资源是隔离的
|
30
chaleaochexist OP @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 实时读取这个环境变量. @错了的花, 见谅. |
31
chaleaochexist OP |
32
pkoukk 350 天前 1
我见识少,有什么语言的多线程是通过多进程实现的嘛?
|
33
ysc3839 350 天前 via Android
@chaleaochexist 26 楼已经回答了,没问题
|
34
chaleaochexist OP |
35
chaleaochexist OP |
36
importlau 350 天前
@chaleaochexist 是的, 同一个进程下的。
|
37
ysc3839 350 天前 via Android
@pkoukk 用户模式线程或者说协程不能用多进程来实现,但是一些子逻辑是可以用多进程的。
因为 Unix 有 fork 可以很方便地保留数据启动新进程,有些程序的子逻辑(比如处理客户端的请求)就会 fork 一下再处理。 |
38
chaleaochexist OP |
39
chaleaochexist OP @Ericcccccccc
标题和内容完全不搭啊... 回到你的问题, 实时修改环境变量能不能生效得看这个值是啥时候读的. 假设两个 goroutine 一个随机写 一个随机读 要求每次都读到最新的环境变量. 如果这两个 goroutine 在两个进程下. 默认是不行的. |
40
proxytoworld 350 天前
@chaleaochexist 同一个进程 环境变量是一份的
|
41
mightybruce 350 天前
多个 goroutine 并不对应多进程,除非你通过 syscall 在代码主动去创建进程。
你改了环境变量,其他 goroutine 是感知不到的, 除非再次主动去读。 多个 goroutine 在一个进程中。 |
42
e7 350 天前
以前找工作的时候经常遇到面试官问类似这种问题,一脸懵逼
|
43
awalkingman 350 天前
你是不是想问不同 goroutine 之间的通信机制?
|
44
bler 350 天前 1
我大概明白楼主是啥意思,楼主应该是想问,main1.go 和 main2.go 独立运行,会不会被 go 语言分配到同一个进程之中。我被 python 的 scrapy 框架坑过,scrapy crawl 命令运行爬虫的时候,scrapy crawl spider1 和 scrapy crawl spider2 是运行在同一个进程之下的,pipeline 的类变量在两个爬虫中会共用,估计楼主应该是遇到类似的问题了
|
45
xdeng 350 天前
单进程是常态吧
|
46
xsen 350 天前
|
47
Immortan 350 天前 2
- Golang 不是单进程的,GOMAXPROCS 默认等于运行时机器的 runtime.NumCPU()
- 但是开发者不用关心,这是 OS 层面的抽象,OS 会保证即使实际运行在多核上,其行为也和运行在单核上一样,比如环境变量的变化。 - 环境变量是 OS 管理的,读取、修改环境变量都需要通过系统调用进入内核态,自然会在所有 goroutine 中生效。 - 一般非常少会通过环境变量的运行时改变来控制代码行为,尤其像 Golang 这种原生对并发支持力度就很大的语言。如上所述,环境变量的读取需要通过系统调用,某种程度上是个"很贵"的操作。 |
48
jdkxnktkdkxod 350 天前
这个问题槽点太多,不知道该怎么回答
|
49
LindsayZhou 350 天前 1
是不是可以这样想,goroutine 之间是可以共享全局变量的,那么表示所有的 goroutine 是共用一套内存地址空间的。
而环境变量存储的位置,如果我没记错,是在程序入口前面一小段的内存里面,既然所有的内存空间是共享的,那么这段环境变量的内存也是共享的。 这样就摆脱了线程进程的概念,不用考虑那些了。 (如果是进程,那内存页就是 COW 了) |
50
ygtq 350 天前
@chaleaochexist 多 goroutine 是否在同一个进程下? 我的理解是,肯定在。因为你没有主动 fork ,golang 也不会主动多开一个进程,go 只是一个静态编程语言,换言之你用 c/c++写,编译生成可执行程序,代码不主动开进程,语言不会开的啊
|
51
kiripeng 350 天前
Happens-Before 原则
|
52
EspoirBao 350 天前
看到单进程的时候突然小脑猥琐了一下,在想是什么情况下需要改多进程的环境变量,进程一般都属于 OS 级别控制的吧???
|
53
zmaplex 350 天前 via Android
不管什么语言,只要不 fork 就是天王老子来了都是单进程。要多进程,只要不主动加锁限制,都可以多进程运行(系统限制除外)
|
54
standchan 350 天前
你没 exec 操作,goroutine 就是一定是单进程,然后 goroutine 是在语言层面复用 os 的线程。此外,我写了 demo 代码,结果是其他 goroutine 也可以读到新修改的环境变量,前提的实时去读。
|
55
RedisMasterNode 350 天前
@dw2693734d 楼主问这个问题肯定是有他背景,例如 Python 进程经常用 Gunicorn 或者 uwsgi 托管,这些都会导致应用程序以多个进程形式运行。
我觉得大家回答不用太过抠字眼了...其实就是个快问快答,但是较真(较真不代表不好)的人很多,才搞得帖子这样... 包括一些什么可以 os.Exec 扩展多进程,拜托,别的语言一样可以,补充这种信息对回答问题一点帮助都没有,不如直接点明 Go 和其他语言的区别在哪里简洁明了。 |
56
ding2dong 350 天前
当然可以啊,goroutine 是线程不是进程
|
57
aisk 350 天前
@RedisMasterNode 他背景他说了,一个 goroutine 里设置环境变量另外一个读不到,然后不怀疑自己代码有 bug ,怀疑 go 是多进程运行不同 goroutine 。
|
58
chaleaochexist OP @aisk 不是怀疑 我还没开始写呢.
提前做点调查. |
59
chaleaochexist OP @standchan 这个东西不能通过 demo 去验证.
当然了严谨一点说 可以证伪. 但是不能验证正确. 譬如 runtime 有一种机制, 当 goroutine < 5. 或者换个说法 count(runtime) < 5 是单进程, >=5 是多进程模式. 所以我发帖上来问问, 不知道为什么楼上一堆冷嘲热讽. |
60
chaleaochexist OP |
61
chaleaochexist OP @kiripeng 大佬这是另一个问题了.
大佬能通俗易懂的解释一下 什么是 Happens-Before 吗? |
62
chaleaochexist OP @ygtq go 和 c++的区别是 go 有一个 goroutine 这个东西是由 runtime 控制的. 所以才上来确认一下.
通常来说确实应该是单进程. |
63
aisk 350 天前
@chaleaochexist 动手测试一分钟,群里讨论一整天。
|
64
chaleaochexist OP @aisk 这个东西不能通过 demo 去验证.
当然了严谨一点说 可以证伪. 但是不能验证正确. 譬如 runtime 有一种机制, 当 goroutine < 5. 或者换个说法 count(runtime) < 5 是单进程, >=5 是多进程模式. 所以我发帖上来问问, 不知道为什么楼上一堆冷嘲热讽. |
65
standchan 349 天前
我没有找到你说的 golang runtime 当协程数量大于一定数目就变成了多进程模式。你在哪里看到的资料能发出来看一下吗?我认为多进程肯定不合理,进程之间的通信要比协程之间的通信复杂太多了,还涉及到了各种同步等等乱七八糟的。另外,你起初问的问题确实特别让人费解,标题和正文我找不到逻辑的相关性
|
66
standchan 349 天前
另外 runtime 对 goroutine 的控制也是基于系统进程里面进行的。它是在进程下面的,当然 exec 会生成新的进程,但生成的进程和 golang 程序所在的进程完全没关系。runtime 也不可能凌驾于进程们之上去管理多个进程。go 是面向云原生高并发,如果是你说的多进程模式,那延迟会高很多很多。
|
67
aisk 349 天前
@chaleaochexist 错的不是你。
|
68
chaleaochexist OP |
69
standchan 349 天前
@chaleaochexist #68 嗯嗯,那现在应该知道结果了就行了。另外,问题的描述可以再提升一下,看起来真的会让人有点懵。
|
70
voidmnwzp 349 天前
…你告我哪个语言不是单进程的
|
71
qwq11 349 天前 via Android
op 去看下操作系统,环境变量是在进程启动的时候被 OS 压到程序的栈里的,所以说是静态的,而不是动态读取。如果你说的是在同一进程下的 goroutine ,显然不会生效,如果你说的是不同进程的 goroutine ,并且在修改完了之后才启动新进程,那答案是会生效
你在 #30 说的情况,答案是不会生效 |
72
chaleaochexist OP @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")) } ``` |
73
CrazyMonkeyV 349 天前
@chaleaochexist 前面我觉得你菜就算了,谁没菜过?看到后面有点逆天。程序员不是自己搞 demo 来证明,靠不明需求的论坛? 6666
|
74
Masoud2023 349 天前
|
76
chaleaochexist OP @Masoud2023 因为我 B 了一些人不知道你说的 72 楼是哪个.
也不算共享内存吧. 就是在不停机的情况下 动态切换 kafka 的配置. 且 if flag == 1 then 从环境变量读配置 else 从数据库读配置. 那我之前的想法是当从数据库读配置之后, 写到环境变量中, 这样其他代码就不用动了. 然后就发帖问问题了. 说得通吗? |
77
pkoukk 349 天前
@chaleaochexist #76
有这种需求,一般我们会搞个 etcd ,redis 也行啊。 你这个玩法让人真是搞不懂,线上部署的时候直接跑二进制,不用 docker ? 不用 docker 隔离环境罢了,还用环境变量,这么信任跑在这台机器上的其它服务? 说到进程问题,我用过的语言里,只要你不 fork ,它们就是共用完全相同的上下文和内存,别管他在 cpu 里有几个实例,那是 os 的事情,和语言无关。 |
78
qwq11 349 天前
@chaleaochexist #72 你是对的,去研究了下 linux 确实可以修改本进程的环境变量,修改之后 OS 会重新给进程分配环境变量表,这点有点出乎意料
#76 的需求建议用变量存,把 os.Getenv 换成 KafkaConfigProvisioner.GetConfig 也用不了多少时间,比你发帖回帖快,用环境变量还得上信号量或者读写锁 |
79
chaleaochexist OP |
80
chaleaochexist OP |
81
tonghuashuai 349 天前
跟 GOMAXPROCS 有关吧,GOMAXPROCS 默认为 CPU 核心数,GOMAXPROCS 参数来确定线程数。
然后 Go 运行时调度使用 m:n 策略,复用 m 个 goroutine 到 n 个线程。 |
82
chaleaochexist OP @qwq11 还有就是其实不需要信号量和读写锁. 这个和我的具体业务有关. 具体就不展开讲了.
|
83
Jooeeee 349 天前
语言跟操作系统是两码事儿,进程分为线程,线程使用一小块内存构造 goroutine ,由于进程的所有现成共享内存,因此 goroutine 可以在不同的线程上跑。golang 可以在 goroutine 中启动新的进程
|
84
mightybruce 349 天前
你选择用环境变量实现,可以说是非常差的方式, 有非常多的方式可以实现
1. 服务通过读取一些第三方配置中心来动态改变,比如 etcd, nacos 2. 服务中直接写一个 http 控制服务,接受请求直接切换。 |
85
dyllen 336 天前 1
单进程多线程,编译一个 exe 出来,只有一个进程,系统线程默认是和 cpu 核数是相等的,一个 goroutine 的执行是在线程里面执行的,不一定是哪个线程。go 的 goroutine 是共享内存的,一个全局变量可以多个 goroutine 修改和读取,会互相影响。
|