并行程序中的Scala模式匹配
我是Scala新手,我想写一些带有模式匹配的多线程代码,我想知道是否可以将模式匹配代码视为原子代码 例如:并行程序中的Scala模式匹配,scala,concurrency,pattern-matching,Scala,Concurrency,Pattern Matching,我是Scala新手,我想写一些带有模式匹配的多线程代码,我想知道是否可以将模式匹配代码视为原子代码 例如: abstract class MyPoint case class OneDim(x : Int) extends MyPoint case class TwoDim(x : Int, y : Int) extends MyPoint var global_point : MyPoint = new OneDim(7) spawn { Thread.sleep(scala.ut
abstract class MyPoint
case class OneDim(x : Int) extends MyPoint
case class TwoDim(x : Int, y : Int) extends MyPoint
var global_point : MyPoint = new OneDim(7)
spawn {
Thread.sleep(scala.util.Random.nextInt(100))
global_point = new TwoDim(3, 9)
}
Thread.sleep(scala.util.Random.nextInt(100))
match global_point {
case TwoDim(_, _) => println("Two Dim")
case OneDim(_) => println("One Dim")
}
是否可能按照以下方式执行:
Scala是否在内部避免了这种执行?如果是这样的话,怎么办?匹配是否拍摄对象的快照,然后尝试将其与模式匹配?快照深度是否有限制(匹配模式可能是复杂的和嵌套的)?我不认为为模式匹配生成的代码中存在任何类型的锁定或快照。如果是,它肯定会在语言规范中提到。这就是说,如果您将模式匹配代码放入一个方法中,您至少可以确保该方法所传递的引用在该方法执行时不会更改。如果TwoDim和OneDim也是不可变的,那么就不需要担心线程安全性。即使它们不是不可变的,只要您在它们的可变字段之一上不匹配也无所谓。在Scala中,首选的并发解决方案是使用
Actor
s。在那些Actor
s中,您需要使用模式匹配来添加行为。我使用scalasActor
构建了一个与您类似的示例
import scala.actors.Actor
import scala.actors.Actor._
abstract class MyPoint
case class OneDim(x: Int) extends MyPoint
case class TwoDim(x: Int, y: Int) extends MyPoint
case object Next
case object End
class OneDimSlave extends Actor {
def act() {
println("Starting OneDimSlave")
loop {
receive {
case End => println("Stoping OneDimSlave"); exit()
case Next => sender ! OneDim(scala.util.Random.nextInt(100))
}
}
}
}
class TwoDimSlave extends Actor {
def act() {
println("Starting TwoDimSlave")
loop {
receive {
case End => println("Stopping TwoDimSlave"); exit()
case Next => sender ! TwoDim(scala.util.Random.nextInt(100),scala.util.Random.nextInt(100))
}
}
}
}
class Master extends Actor {
val oneDimSlave = new OneDimSlave
val twoDimSlave = new TwoDimSlave
oneDimSlave.start
twoDimSlave.start
def act {
println("Starting Master")
for (_ <- 0 to 9) { oneDimSlave ! Next; twoDimSlave ! Next }
var count = 0
loop {
if (count >= 20) { oneDimSlave ! End; twoDimSlave ! End; println("Stopping Master"); exit() }
receive {
case _ :OneDim => count += 1; println(count + ". One Dim")
case _: TwoDim => count += 1; println(count + ". Two Dim")
}
}
}
}
object Main extends App {
val master = new Master
master.start
}
这不是来自规范的确凿证据,但它说明了编译器为您所做的一些事情,这应该允许您将少数匹配块视为原子块,但肯定不是所有的。如果您自己同步代码,或者使用不可变对象,则会更加安全 简单的例子 如果使用scala-print运行以下脚本:
var m: Option[String] = _
m match {
case Some(s) => "Some: " + s
case None => "None"
}
您将看到由编译器创建的经过去糖处理的中间代码(为了简洁起见,我删除了一些代码):
编译器将创建以下中间代码:
private[this] var x: anonymous class Main$$anon$1$X = _;
private <accessor> def x(): anonymous class Main$$anon$1$X = Main$$anon$1.this.x;
final <synthetic> private[this] def gd2$1(x$1: Int, x$2: anonymous class Main$$anon$1$X): Boolean = x$1.>(0).||(x$2.f().>(0));
final <synthetic> private[this] def gd3$1(x$1: Int, x$2: anonymous class Main$$anon$1$X): Boolean = x$1.<=(0).||(x$2.f().<=(0));
def this(): anonymous class Main$$anon$1 = {
<synthetic> val temp6: anonymous class Main$$anon$1$X = Main$$anon$1.this.x();
if (temp6.ne(null)) {
<synthetic> val temp7: Int = temp6.f();
<synthetic> val temp8: anonymous class Main$$anon$1$X = temp6.x();
if (Main$$anon$1.this.gd2$1(temp7, temp8))
"gt0"
else if (Main$$anon$1.this.gd3$1(temp7, temp8))
"lte0"
else
throw new MatchError(temp6)
} else
throw new MatchError(temp6)
}
private[this]变量x:匿名类Main$$anon$1$x=\;
private def x():匿名类Main$$anon$1$x=Main$$anon$1.this.x;
final private[this]def gd2$1(x$1:Int,x$2:anonymous类Main$$anon$1$x):Boolean=x$1.>(0)。| |(x$2.f().>(0));
final private[this]def gd3$1(x$1:Int,x$2:anonymous类Main$$anon$1$x):Boolean=x$1。
final class Main$$anon$1 extends java.lang.Object {
private[this] var m: Option = _;
private <accessor> def m(): Option = Main$$anon$1.this.m;
def this(): anonymous class Main$$anon$1 = {
<synthetic> val temp1: Option = Main$$anon$1.this.m();
if (temp1.$isInstanceOf[Some]()) {
"Some: ".+(temp1.$asInstanceOf[Some]().x())
else if (scala.this.None.==(temp1))
"None"
else
throw new MatchError(temp1)
}
}
case class X(var f: Int, var x: X)
var x = new X(-1, new X(1, null))
x match {
case X(f, ix) if f > 0 || ix.f > 0 => "gt0"
case X(f, ix) if f <= 0 || ix.f <= 0 => "lte0"
}
private[this] var x: anonymous class Main$$anon$1$X = _;
private <accessor> def x(): anonymous class Main$$anon$1$X = Main$$anon$1.this.x;
final <synthetic> private[this] def gd2$1(x$1: Int, x$2: anonymous class Main$$anon$1$X): Boolean = x$1.>(0).||(x$2.f().>(0));
final <synthetic> private[this] def gd3$1(x$1: Int, x$2: anonymous class Main$$anon$1$X): Boolean = x$1.<=(0).||(x$2.f().<=(0));
def this(): anonymous class Main$$anon$1 = {
<synthetic> val temp6: anonymous class Main$$anon$1$X = Main$$anon$1.this.x();
if (temp6.ne(null)) {
<synthetic> val temp7: Int = temp6.f();
<synthetic> val temp8: anonymous class Main$$anon$1$X = temp6.x();
if (Main$$anon$1.this.gd2$1(temp7, temp8))
"gt0"
else if (Main$$anon$1.this.gd3$1(temp7, temp8))
"lte0"
else
throw new MatchError(temp6)
} else
throw new MatchError(temp6)
}