Странное поведение при создании ForkJoinTask для многопоточности в цикле Scala

Задача состоит в том, чтобы преобразовать значения из массива src и записать новые значения в массив dst.

Когда я создаю ForkJoinTasks в цикле while

val height: Int = 4;
val numTasks: Int = 2;

var tasks = scala.collection.mutable.ListBuffer.empty[ForkJoinTask[Unit]]

val jump: Int = src.height / numTasks
var from: Int = 0;

while (from < height) {
  val end: Int = height.min(from + jump);
  val t: ForkJoinTask[Unit] = task {
    run(src, dst, from, end) // (2,2), (2,1), what is happening?
  }
  from = end
}

for (t <- tasks.toList) {
  t.join()
}

Затем, как ни странно, функция запуска принимает значение аргумента (от, конец) как (2, 2). Но если разбить вручную на две задачи, то работает нормально, как (0,1) так и (1,2).

val t1 = task {
  run(src, dst, 0, height / 2); // (0, 1)
}
val t2 = task {
  run(src, dst, height / 2, height); // (1, 2)
}

t1.join()
t2.join()

Мне трудно понять, что происходит. Это моя самая первая программа на Scala, поэтому я мог упустить что-то очень тривиальное. Любой комментарий будет оценен.

Спасибо.


person user557583    schedule 21.09.2016    source источник
comment
Пожалуйста, определите src и dest ¿любая связь с высотой val?   -  person Krlos    schedule 21.09.2016
comment
src и dst — это массивы. run читает значения из src, записывает новые в dst.   -  person user557583    schedule 22.09.2016


Ответы (1)


Удаление ссылок на src или dst в вашем коде выглядит нормально, так как возвращает диапазоны

0 2
2 4

import shapeless.PolyDefns.~>
import shapeless.{ HList, HNil }
import io.netty.util.internal.chmv8.ForkJoinTask

object main extends App {

  val height: Int = 4;
  val numTasks: Int = 2;

  var tasks = scala.collection.mutable.ListBuffer.empty[ForkJoinTask[Unit]]

  val jump: Int = height / numTasks
  var from: Int = 0;

  while (from < height) {
    val end: Int = height.min(from + jump);
    val t: ForkJoinTask[Unit] =  {
      run( from, end) // (2,2), (2,1), what is happening?
    }
    from = end
  }

  for (t <- tasks.toList) {
    t.join()
  }


  def run (from: Int, end:Int) ={
    println(s"$from $end")
    null
  }

}
person Krlos    schedule 23.09.2016
comment
Я понял, почему. Имея from as var, он ссылается на него, поэтому, когда его значение изменяется в цикле, значение, переданное в функцию run, также изменяется. В вашем примере такое не поймается, но если вы сделаете более тяжелые расчеты в функции запуска, вы это заметите. - person user557583; 23.09.2016