Collection.parallelStream()是否暗示先发生关系? [英] Does Collection.parallelStream() imply a happens-before relationship?

查看:157
本文介绍了Collection.parallelStream()是否暗示先发生关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下(完全人为设计的)Java代码:

Consider this (completely contrived) Java code:

final List<Integer> s = Arrays.asList(1, 2, 3);
final int[] a = new int[1];
a[0] = 100;
s.parallelStream().forEach(i -> {
    synchronized (a) {
        a[0] += i;
    }
});
System.out.println(a[0]);

此代码是否保证输出"106"?

Is this code guaranteed to output "106"?

除非是由parallelStream()建立的 happens-before 关系,否则似乎不是这样,通过该关系我们可以肯定地知道对lambda中的a[0]的首次访问将看到100而不是零(根据我对Java内存模型的理解).

It seems like it is not unless there is a happens-before relationship established by parallelStream(), by which we can know for sure that the first accesses to a[0] in the lambda will see 100 and not zero (according to my understanding of the Java memory model).

但是Collection.parallelStream()并没有证明可以建立这种关系...

But Collection.parallelStream() is not documented to establish such a relationship...

可以问相同的问题来完成parallelStream()方法调用.

The same question can be asked for the completion of the parallelStream() method invocation.

那么我是不是缺少了什么?或者为正确起见,是否需要上面的代码看起来像这样呢?

So am I missing something, or is it true that for correctness would the above code be required to look something like this instead:

final List<Integer> s = Arrays.asList(1, 2, 3);
final int[] a = new int[1];
synchronized (a) {
    a[0] = 100;
}
s.parallelStream().forEach(i -> {
    synchronized (a) {
        a[0] += i;
    }
});
synchronized (a) {
    System.out.println(a[0]);
}

或者... parallelStream()确实提供了这些先发生关系,而这仅仅是一些缺少文档的问题吗?

Or... does parallelStream() actually provide these happens-before relationships, and this simply a matter of some missing documentation?

我之所以问是因为,从API设计的角度来看,(至少对我来说)这样做似乎是合乎逻辑的……类似于Thread.start()等.

I'm asking because from an API design perspective, it seems (to me at least) like this would be a logical thing to do... analogous to Thread.start(), etc.

推荐答案

您真的应该避免在管道外部"访问变量.即使您使其正常工作,性能也可能会受到影响. JDK内置了许多工具来实现此目的.例如,您的用例可能更安全,例如:

You really should avoid hitting variables 'outside' the pipeline. Even if you get it to work correctly performance will likely suffer. There are a lot of tools to achieve this built into the JDK. For example your use case is probably safer with something like:

Integer reduce = IntStream.of(1, 2, 3)
            .parallel()
            .reduce(100, (accumulator, element) -> accumulator + element);

这篇关于Collection.parallelStream()是否暗示先发生关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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