并发与并行在Golang中的区别

huangapple go评论80阅读模式
英文:

Concurrency vs parallelism in Golang

问题

我正在尝试在Golang和Rust中实现双比较并交换(可能还有MWCAS),由于没有CPU支持该指令,我需要找到一种使用语言提供的功能的方法。

让我们看一下这段代码:

func HttpServer(parallelism int) {

    runtime.GOMAXPROCS(parallelism)

    called := 0

    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        time.Sleep(2 * time.Second)
        called++
        fmt.Fprint(w, called)
    })

    http.ListenAndServe(":8090", nil)
}

总体上来说,这段代码是错误的,但是如果我们调用HttpServer(1),它会按预期工作:假设我调用端点1000次,在不到3秒的时间内,我将得到1000个不同的called值,从1到1001。这是因为如果我们使用parallelism = 1执行,Go运行时将把time.sleep后的处理程序作为原子代码块执行,同时等待所有其他处理程序。

使用这个技巧,我可以轻松实现DCAS和MWCAS,而无需使用原子操作(慢5倍)或互斥锁(慢25倍)。

我的问题是:

  • 这段代码有什么问题吗?我是否遗漏了一些细节?为什么即使将parallelism设置为1,竞争检测器仍然检测到竞争条件?(但结果是正确的,所以似乎不会影响输出)

  • 有没有办法为每个goroutine及其子goroutine设置runtime.GOMAXPROCS?例如,一个goroutine及其子goroutine将以parallelism 1执行,而另一个goroutine将以parallelism 10执行。目前我唯一看到的方法是启动多个进程,然后通过IPC进行通信。

英文:

I'm trying to implement double compare and swap (and maybe MWCAS) both in Golang and Rust, and since no CPU supports this instruction I need to find a way using what the language offers me.

Let's take this code:

func HttpServer(parallelism int) {

    runtime.GOMAXPROCS(parallelism)

    called := 0

 http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
     time.Sleep(2 * time.Second)
     called++
     fmt.Fprint(w, called)
    })

    http.ListenAndServe(":8090", nil)
}

In general it's wrong, but if we call HttpServer(1) it works as expected: let's say I call the endpoint 1000 times, I will get 1000 different values of called, from 1 to 1001, in less than 3 seconds. This is because if we execute with parallelism = 1 the go runtime will execute the handler after time.sleep as an atomic block of code, while waiting for all the other handlers at once.

Using this trick I can implement DCAS and MWCAS with little effort, without using atomics (5x slower) or mutexes (25x slower)

My questions are:

  • Is anything wrong with this code? Am I missing some details? Why the race detector still detect races even with parallelism set to 1? (but the results are correct, so it doesn't seem to affect output)

  • Is there a way to set runtime.GOMAXPROCS per goroutine and its descendants? so for example one goroutine and its children will execute with parallelism 1, while another will execute with parallelism 10. For now the only way I see is to launch multiple processes and then communicate with IPC.

答案1

得分: 3

这段代码有什么问题吗?

是的,它存在竞争条件(racy)。

有没有办法为每个 goroutine 及其子 goroutine 设置 runtime.GOMAXPROCS?

没有。

英文:

> Is anything wrong with this code?

Yes, it's racy.

> Is there a way to set runtime.GOMAXPROCS per goroutine and its descendants?

No.

huangapple
  • 本文由 发表于 2022年8月22日 19:04:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/73444078.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定