parallelsim

时间:2017-08-15 06:35:07

标签: scala memory concurrency parallel-processing

在Scala - 关于coursera的函数式编程课程中,以下片段在并发案例中被描述为失败。如果mutable.Set被并发类替换,则代码段将成功。

def intersection(a: GenSet[Int], b: GenSet[Int]): Set[Int] = {
val result = mutable.Set[Int]()
for (x <- a) if (b contains x) result += x
result
}
intersection((0 until 1000).toSet, (0 until 1000 by 4).toSet)
intersection((0 until 1000).par.toSet, (0 until 1000 by 4).par.toSet)
  

规则:避免在没有适当的情况下突然转移到相同的内存位置   同步。

并发和非并发类之间的区别是什么,或者并发类在并行化下可能失败的原因是什么?

2 个答案:

答案 0 :(得分:2)

如果同时将元素附加到设置而没有同步,则设置无法正确处理冲突或错误地计算位置。因此,对于您的示例,res2可能会有重复字段或更少某些字段。

移出:

有:

for (x <- a) if (b contains x) result += x
result
}

result += x存在竞争条件。它等于SET ME UP,但对于这种方法,它不是线程安全

var h = index(newEntry.hashCode)
var curEntry = table(h)
while (null != curEntry) {
  if (curEntry == newEntry) return false
  h = (h + 1) % table.length
  curEntry = table(h)
  //Statistics.collisions += 1
}
table(h) = newEntry

在上面的代码中,尝试同时将元素追加到 HashTable 。它可能导致计算错误的位置或遇到错误的碰撞。例如,当尝试将newEntry添加到Set时,实际上它不存在于中,它将直接转到table(h) = newEntry,但同时时间,有一个新值,它与hashcode具有相同的newEntry,但是对于第一个newEntry仍未完成table(h) = newEntry,所以newEntry将被第二值覆盖。

因此对于同步,您可以这样做:

for (x <- a) {
  if (b contains x) {
    this.synchronized {
      result += x
    }
  }
}

答案 1 :(得分:1)

如果您的代码包含可变字段,那么它不是线程安全的。这意味着,您无法同时执行此代码 。并发执行意味着,同时在多个线程中执行相同的代码。

因此,让我们从您的给定代码开始,因为它包含一个可变字段result,并且此字段在for循环内被修改/变异。

def intersection(a: GenSet[Int], b: GenSet[Int]): Set[Int] = {
val result = mutable.Set[Int]() //This field is not thread safe.
    for (x <- a) if (b contains x) result += x      //mutation occured here.
    result
}

现在,让我们看看第一种情况的执行情况:intersection((0 until 1000).toSet, (0 until 1000 by 4).toSet)。在这里,您提供了值为0 to 1000的Set。现在,在for loop中,当迭代此集合时,执行将是顺序的。即x的值从0 till 1000顺序写入结果。因此,代码执行时没有任何错误。

现在,让我们看看第二个方案intersection((0 until 1000).par.toSet, (0 until 1000 by 4).par.toSet)。在这种情况下,您提供的集合为Parallel set。因此,在for loop中,突变/写入结果字段同时发生。因此,线程之间将存在竞争条件以便写入数据,因此该执行不是线程安全的并且将失败。要避免此问题,必须按照其他答案中的描述同步对结果的写访问权限,否则,它将不是线程安全的。

因此,有一个并发规则:

  

&#34;避免在没有适当的情况下突然转移到相同的内存位置   同步&#34;