Golang,如何分享价值 - 消息或互斥?

Hon*_*oon 0 mutex channel go

我已经完成了简单的基准测试,其中一个在消息传递和锁定共享值方面更有效.

首先,请检查下面的代码.

package main

import (
    "flag"
    "fmt"
    "math/rand"
    "runtime"
    "sync"
    "time"
)

type Request struct {
    Id      int
    ResChan chan Response
}

type Response struct {
    Id    int
    Value int
}

func main() {
    procNum := flag.Int("proc", 1, "Number of processes to use")
    clientNum := flag.Int("client", 1, "Number of clients")
    mode := flag.String("mode", "message", "message or mutex")
    flag.Parse()

    if *procNum > runtime.NumCPU() {
        *procNum = runtime.NumCPU()
    }

    fmt.Println("proc:", *procNum)
    fmt.Println("client:", *clientNum)
    fmt.Println("mode:", *mode)

    runtime.GOMAXPROCS(*procNum)

    rand.Seed(time.Now().UnixNano())
    var wg sync.WaitGroup

    sharedValue := 0

    start := time.Now()

    if *mode == "message" {
        reqChan := make(chan Request) // increasing channel size does not change the result
        go func() {
            for {
                req := <-reqChan
                sharedValue++
                req.ResChan <- Response{Id: req.Id, Value: sharedValue}
            }
        }()

        for i := 0; i < *clientNum; i++ {
            wg.Add(1)
            go func(index int) {
                defer wg.Done()
                c := make(chan Response)
                defer close(c)
                id := rand.Int()
                reqChan <- Request{Id: id, ResChan: c}
                <-c
            }(i)
        }
    } else if *mode == "mutex" {
        mutex := &sync.Mutex{}

        for i := 0; i < *clientNum; i++ {
            wg.Add(1)
            go func(index int) {
                defer wg.Done()
                mutex.Lock()
                sharedValue++
                mutex.Unlock()
            }(i)
        }
    }

    wg.Wait()
    elapsed := time.Since(start)

    fmt.Println("Elapsed:", elapsed, "value:", sharedValue)
}
Run Code Online (Sandbox Code Playgroud)

正如您已经注意到的,程序相对简单.在消息模式下,它通过消息传递增加sharedValue.在互斥模式下,它通过锁定增加sharedValue.

我试图只使用一个频道进行消息模式并放弃了.我想这可能不可能,不是吗?

我的电脑有2个Xeon CPU,每个都有6个核心.由于超线程,逻辑上可以使用24个内核.它的公羊尺寸是12G.

如果我使用任何数字运行程序的标志,互斥模式总是最快2倍(通常是3次).

好的,我可以理解管理渠道需要一定的成本.那么,如果我只考虑性能,有没有理由使用channel而不是mutex?另外,消息传递成本可以被巨大的消息大小忽略吗?

Von*_*onC 8

如果我只考虑性能,有没有理由使用频道而不是互斥?

并不是的.维基页面" 使用一个sync.Mutex或一个频道? "说要使用最具表现力和/或最简单的那个.
有一个用于Mutex的频道示例,但评论如下:

虽然通道为受保护的数据提供了一个很好的解决方案,但对于一个作者和许多读者而言,它是一种效率较低的解决方案

这个主题增加了:

如果您正在共享数据,并且永远不会在锁定部分中阻塞,请使用互斥锁.
在非阻塞情况下,互斥锁真的很便宜.

如果你有一些复杂或冗长的共享服务,并且必须进行序列化,请考虑给它自己的goroutine,它接收来自通道的请求并在完成时发回回复.通常你发送一个struct带有输入参数和一个用于回复的通道对象.
这很像RPC.

通道用于通信,而不是锁定.
如果您通过通道发送无意义的数据仅用于锁定目的,那么您可能会过度复杂化.