go - 通道值的互斥写入锁定
问题描述
我有一个包含数千个 ID 的通道,需要在 goroutines 中并行处理。我如何实现一个锁,以便 goroutines 不能同时处理相同的 id,是否应该在通道中重复?
package main
import (
"fmt"
"sync"
"strconv"
"time"
)
var wg sync.WaitGroup
func main() {
var data []string
for d := 0; d < 30; d++ {
data = append(data, "id1")
data = append(data, "id2")
data = append(data, "id3")
}
chanData := createChan(data)
for i := 0; i < 10; i++ {
wg.Add(1)
process(chanData, i)
}
wg.Wait()
}
func createChan(data []string) <-chan string {
var out = make(chan string)
go func() {
for _, val := range data {
out <- val
}
close(out)
}()
return out
}
func process(ids <-chan string, i int) {
go func() {
defer wg.Done()
for id := range ids {
fmt.Println(id + " (goroutine " + strconv.Itoa(i) + ")")
time.Sleep(1 * time.Second)
}
}()
}
--edit: 所有值都需要以任意顺序处理,但“id1,”id2”和”id3”需要阻塞,因此它们不能被多个goroutine同时处理。
解决方案
这里最简单的解决方案是根本不发送重复值,然后不需要同步。
func createChan(data []string) <-chan string {
seen := make(map[string]bool)
var out = make(chan string)
go func() {
for _, val := range data {
if seen[val] {
continue
}
seen[val] = true
out <- val
}
close(out)
}()
return out
}
推荐阅读
- php - 拉拉维尔 5.6。失败,如果请求中存在 2 个特定字段
- ios - 2 个方法 performFetchWitchCompletionHandler 和 didReceiveRemoteNotification 的 completionHandler 是否相互干扰?
- c - 如何在C中获取Trie中最长前缀的长度
- spring - Spring boot - 如何覆盖spring security中的默认用户名和密码
- javascript - 无法在 Ext JS 应用程序中包含 ux
- python - 如何将值存储为特定于用户的全局变量?
- sql - 将日文字符插入 SQL Server 数据库
- multithreading - 带有 moveThreadCount=1 的 Optaplanner 配置与没有 moveThreadCount 不同
- r - 是否可以将 R 中的多个数据帧合并为一个数据,其中所有列的键都相同
- python - 如何使用 Python 和 patoolib 解压缩 .rar 文件