Scala-以线程安全的方式从parallel for访问阵列

Scala-以线程安全的方式从parallel for访问阵列,scala,Scala,我有以下代码: //variable arrayToAccess is an array of integers //anotherArray holds integers also anotherArray.par.foreach{ item => val mathValue = mathematicalCalculation(item) if (mathValue > arrayToAccess.last) { //append element

我有以下代码:

//variable arrayToAccess is an array of integers
//anotherArray holds integers also
anotherArray.par.foreach{ item =>
    val mathValue = mathematicalCalculation(item)
    if (mathValue > arrayToAccess.last) {
        //append element
        arrayToAccess :+= mathValue
        //sort array and store it in the same variable
        arrayToAccess = arrayToAccess.sortWith((i1,i2) => i1 > i2).take(5)
    }
}
我认为以这种方式访问arrayToAccess变量不是线程安全的。如何以线程安全的方式实现上述代码?另外,我能控制另一个AARAY.PAR的并行级别(例如,只使用8个可用的2个内核)?如果没有,有办法控制它吗?

你想得太多了。 只要做:

arrayToAccess = anotherArray.par
  .map { mathematicalCalculation _ }
  .seq
  .sorted
  .reverse
  .take(5)
它产生的结果与代码预期的结果相同,但是线程安全的

更新如果您担心排序步骤所需的时间,您可以选择线性时间中的前五位:

val top(data: Array[Int], n: Int) = {
val queue = PriorityQueue()(Ordering[Int].reverse)
data.fold(queue) { case(q,n) => 
   q.enqueue(n) 
   while(q.size > 5) q.dequeue
   queue
}
.toArray
.sorted
.reversed
关于配置并行性,我认为这应该有帮助:

更新如果您关心排序步骤,可以将其替换为并行排序或在线性时间内折叠到有界优先级队列中,如下所示:

 def topN(data: Array[Int], n: Int) = {     
   val queue = PriorityQueue()(Ordering[Int].reverse) 
   data.foldLeft(queue) { case (q, x) => 
     q.enqueue(x)
     while(q.size > n) q.dequeue
     q
   }.dequeueAll.reverse

.seq.sorted.reverse.take(5)
如果另一个数组变量很大,则sorted方法和reverse方法需要时间,不是吗?特别是如果它是一个更复杂的排序方法。@Sonex,它不再比原始数组“庞大”。考虑一下,如果后者是“巨大”的,那么你的方法会对输出进行排序并重新排序一个“巨大”的次数。这可能不会比对合并结果进行一次排序快多少。如果你关心并行性,你可以使用并行排序和合并(有限制),但我认为这太过分了。@Sonex或只是
。在线性时间内将
折叠成一个(有限制的)
PriorityQueue
。你能解释一下你最后的评论吗?