在C#中,这非常简单:
class Class1{
private static readonly object locker = new object();
void Method1(){
lock(locker) { .... }
}
}
我绝对不应该在this
上进行同步,因为它可能会导致死锁。同样,在Scala中,我看到了一些示例,无法了解同步和对象(字段)的基本原理是什么,我应该使用它来进行同步:
#1
def add(user: User) {
// tokenizeName was measured to be the most expensive operation.
val tokens = tokenizeName(user.name)
tokens.foreach { term =>
userMap.synchronized {
add(term, user)
}
}
}
#2
class Person(var name: String) {
def set(changedName: String) {
this.synchronized {
name = changedName
}
}
}
#3 and so on...
你介意为我说清楚吗?
答案 0 :(得分:17)
在Scala中,获得相同的行为更为直接(我假设你想要出于某种原因锁定包含的对象,例如比锁定该类的整个实例更精细的控制):
class Class1 {
private object Locker
def method1 { Locker.synchronized { ... } }
}
但你应该很少以这种方式控制事物。特别是,它不会阻止C#或Scala中的死锁,而不会引起...
的注意。
你至少应该使用java.util.concurrent
中的并发工具,你可能想看看期货或演员。
答案 1 :(得分:15)
在Scala中锁定对象与在Java中对静态字段/类进行锁定相同,这基本上是最难的一个'锁。它将阻止不在类实例上的操作,而是在类加载器范围内的类本身上。在引入这样的锁时你应该仔细考虑。它不会因为获取的锁定顺序错误而保护您免受死锁,而是会导致阻塞线程,如果它们正在处理类的不同实例,并且可能根本不会干扰。
锁定'这个'或者某些类(非对象)字段(mutex)是更宽松的同步方式,您应该使用它来管理不是类的访问 - 而是使用此类的特定实例。
看看akka中的演员,他们摇滚并消除了许多同步问题。
旁注:在'这个'上进行同步并不意味着死锁。
答案 2 :(得分:8)
如果前提是您要避免锁定this
,因为具有第三方代码的另一个线程可以锁定同一个对象,则Scala会提供一个更高级别的可见性private[this]
。
class C {
private[this] val lock = new Object()
def method1(): Unit = lock.synchronized {
println("method1")
}
}
实际上除了C
的特定实例之外,其他任何对象都不能访问lock
。即使来自同一班级的其他实例也无法访问lock
。