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

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

问题描述

我有一个包含要完成的工作的切片,以及一个包含所有完成后的结果的切片。以下是我的一般流程的草图:

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写入任何东西不会让我感觉很好,但是在这种情况下,每个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).

您不要读取切片 elements ,您只能修改切片元素。而且每个goroutine仅修改一个不同指定切片元素。而且,由于每个slice元素都有其自己的地址(自己的内存空间),因此它们就像不同的变量。 规范:变量:

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 的结构化变量, 切片结构类型的元素和字段可能是已寻址个别地。 每个此类元素的行为都像一个变量。

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(),并且在调用 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().

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

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()之后访问结果的元素, code>,这就是数据竞赛:

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()

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

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