我已经完成了简单的基准测试,在传递消息和锁定共享值方面效率更高。
首先,请检查以下代码。
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)
}
您已经注意到,程序相对简单。在 消息模式下 ,它通过消息传递来增加sharedValue。在 互斥锁模式下 ,它通过锁定来增加
sharedValue 。
我尝试只将一个频道用于 消息模式 并放弃了。我认为这不可能,不是吗?
我的计算机有2个Xeon CPU,每个都有6个内核。由于超线程,逻辑上有24个内核可用。它的内存大小是12G。
如果我用任意数量的标志运行程序,则 互斥锁模式 总是至少快2倍(通常是3倍)。
好的,我可以理解,管理渠道需要一定的成本。然后,如果仅考虑性能,是否有任何理由使用通道而不是互斥锁?另外,巨大的消息量可以忽略消息传递成本吗?
如果仅考虑性能,是否有任何理由使用通道而不是互斥锁?
并不是的。维基页面“ 使用一个sync.Mutex
或一个频道? ”说使用最富表现力和/或最简单的那个。
有一个用于Mutex的通道示例,但已注释如下:
尽管通道为受保护的数据提供了很好的解决方案,但是对于一个作者和许多读者来说,它的效率较低。
该线程添加:
如果您要共享数据,并且从不阻塞锁定部分,请使用互斥锁。
在非阻塞情况下,互斥对象确实很便宜 。如果您有一些共享服务执行某些复杂或较长的工作,并且必须对其进行序列化,请考虑为其提供一个自己的goroutine,该例程可接收来自通道的html" target="_blank">请求并在完成后将回复发送回去。通常,您发送
struct
带有输入参数的a和用于回复的通道对象。
这很像RPC。通道用于通信 ,而不是锁定。
如果仅出于锁定目的而通过通道发送无意义的数据,则可能会使事情复杂化。
问题内容: 阅读有关锁定PHP的一些文章。 它们主要都直接指向http://php.net/manual/en/function.flock.php。 本页讨论如何在硬盘上打开文件! 真的是这样吗?我的意思是,这使锁定变得非常昂贵-这意味着每次要锁定时,我都必须访问硬盘)= 能再给我一个令人愉快的消息安慰我吗? 编辑: 由于我已经收到了一些答复,我想问这个。 我的脚本只能由一个或多个线程运行?因为
互斥是多线程系统中用于控制访问的一个原对象(primitive object)。下面的例子给出了它最基本的用法: std::mutex m; int sh; //共享数据 // … m.lock(); // 对共享数据进行操作: sh += 1; m.unlock(); 在任何时刻,最多只能有一个线程执行到lock()和unlock()之间的区域(通常称为临界区)。当第一个线程正在临界区执行时
Go语言包中的 sync 包提供了两种锁类型:sync.Mutex 和 sync.RWMutex。 Mutex 是最简单的一种锁类型,同时也比较暴力,当一个 goroutine 获得了 Mutex 后,其他 goroutine 就只能乖乖等到这个 goroutine 释放该 Mutex。 RWMutex 相对友好些,是经典的单写多读模型。在读锁占用的情况下,会阻止写,但不阻止读,也就是多个 gor
上面的例子中,我们看过了如何在多个协程之间原子地访问计数器,对于更复杂的例子,我们可以使用Mutex来在多个协程之间安全地访问数据。 package main import ( "fmt" "math/rand" "runtime" "sync" "sync/atomic" "time" ) func main() { // 这个例子的状态就
线程使用互斥量保护共享资源 线程使用互斥量保护共享资源 源码/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-08-24 yangjie the first versi
互斥量接口 结构体 struct rt_mutex 互斥量控制块 更多... 类型定义 typedef struct rt_mutex * rt_mutex_t 互斥量类型指针定义 函数 rt_err_t rt_mutex_init (rt_mutex_t mutex, const char *name, rt_uint8_t flag) 初始化互斥量 rt_err