首页 > 解决方案 > 通道值的互斥写入锁定

问题描述

我有一个包含数千个 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同时处理。

标签: go

解决方案


这里最简单的解决方案是根本不发送重复值,然后不需要同步。

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
}

推荐阅读