我可以同时写不同的切片元素吗 [英] Can I concurrently write different slice elements

查看:28
本文介绍了我可以同时写不同的切片元素吗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含要完成的工作的切片,还有一个包含所有完成后的结果的切片.以下是我的大致流程草图:

I have a slice that contains work to be done, and a slice that will contain the results when everything is done. The following is a sketch of my general process:

var results = make([]Result, len(jobs))
wg := sync.WaitGroup{}
for i, job := range jobs {
    wg.Add(1)
    go func(i int, j job) {
        defer wg.Done()
        var r Result = doWork(j)
        results[i] = r
    }(i, job)
}
wg.Wait()
// Use results

它似乎有效,但我没有对其进行彻底的测试,不确定这样做是否安全.一般来说,让多个 goroutine 写入 anything 会让我感觉不好,但在这种情况下,每个 goroutine 仅限于切片中自己的索引,这是预先分配的.

It seems to work, but I have not tested it thoroughly and am not sure if it is safe to do. Generally I would not feel good letting multiple goroutines write to anything, but in this case, each goroutine is limited to its own index in the slice, which is pre-allocated.

我想另一种方法是通过渠道收集结果,但由于结果的顺序很重要,这似乎很简单.以这种方式写入切片元素是否安全?

I suppose the alternative is collecting results via a channel, but since order of results matters, this seemed rather simple. Is it safe to write into slice elements this way?

推荐答案

规则很简单:如果多个 goroutine 访问一个 变量 并发,并且至少有一次访问是写,则需要同步.

The rule is simple: if multiple goroutines access a variable concurrently, and at least one of the accesses is a write, then synchronization is required.

你的例子没有违反这条规则.你不写切片 value(切片头),你只读取它(隐式,当你索引它时).

Your example does not violate this rule. You don't write the slice value (the slice header), you only read it (implicitly, when you index it).

您不读取切片元素,您只修改切片元素.并且每个 goroutine 只修改一个不同指定的切片元素.由于每个切片元素都有自己的地址(自己的内存空间),它们就像不同的变量.这在 规范:变量:

You don't read the slice elements, you only modify the slice elements. And each goroutine only modifies a single, different, designated slice element. And since each slice element has its own address (own memory space), they are like distinct variables. This is covered in Spec: Variables:

结构化变量array切片struct 类型具有可以单独寻址的元素和字段.每个这样的元素就像一个变量.

Structured variables of array, slice, and struct types have elements and fields that may be addressed individually. Each such element acts like a variable.

必须牢记的是,如果没有同步,您将无法从 results 切片中读取结果.您在示例中使用的等待组是足够的同步.一旦 wg.Wait() 返回,您就可以读取切片,因为这只能在所有名为 wg.Done() 的工作程序 goroutine 之后发生,并且没有任何工作程序goroutines 在调用 wg.Done() 后修改元素.

What must be kept in mind is that you can't read the results from the results slice without synchronization. And the waitgroup you used in your example is a sufficient synchronization. You are allowed to read the slice once wg.Wait() returns, because that can only happen after all worker goroutines called wg.Done(), and none of the worker goroutines modify the elements after they called wg.Done().

例如,这是检查/处理结果的有效(安全)方法:

For example, this is a valid (safe) way to check / process the results:

wg.Wait()
// Safe to read results after the above synchronization point:
fmt.Println(results)

但是如果您尝试在 wg.Wait() 之前访问 results 的元素,那就是数据竞争:

But if you would try to access the elements of results before wg.Wait(), that's a data race:

// This is data race! Goroutines might still run and modify elements of results!
fmt.Println(results)
wg.Wait()

这篇关于我可以同时写不同的切片元素吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆