Какой объект я могу синхронизировать в Scala?
В С# это довольно просто:
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...
Не могли бы вы дать мне понять это?
Ответы
Ответ 1
-
Наличие блокировки объекта в Scala совпадает с блокировкой статического поля/класса на Java, которая в основном является одним из "самых сложных" блокировок. Он будет блокировать операции не на экземпляре класса, а на самом классе в рамках класса загрузчика. Вы должны тщательно подумать, вводя подобные блокировки. Он не защищает вас от тупика из-за неправильного упорядочения приобретенных блокировок, но вместо этого приводит к блокировке потоков, если они работают с разными экземплярами класса и могут вообще не вмешиваться.
-
с блокировкой на 'this' или в некотором поле класса (не объект) (мьютекс) более расслабленный способ синхронизации, вы должны использовать его для управления доступом не к классу, а к конкретному экземпляру этого класса.
-
Посмотрите на актеров в akka, они качают и устраняют многие проблемы с синхронизацией.
Примечание: выполнение синхронизации на 'this' не означает взаимоблокировки.
Ответ 2
В Scala это более просто, чтобы получить одно и то же поведение (я предполагаю, что вы хотите заблокировать содержащийся объект по какой-либо причине, например, более мелкозернистый элемент управления, чем блокирование всего экземпляра этого класса):
class Class1 {
private object Locker
def method1 { Locker.synchronized { ... } }
}
Но вы должны редко контролировать вещи таким образом. В частности, он не будет препятствовать взаимоблокировкам в С# или Scala без особого внимания к тому, что входит в ...
.
По крайней мере, вы должны использовать инструменты concurrency в java.util.concurrent
, и вы можете захотеть взглянуть на фьючерсы или актеры.
Ответ 3
Если предпосылка заключается в том, что вы хотите избежать блокировки на this
, потому что другой поток с кодом третьей стороны может блокировать один и тот же объект, тогда Scala предлагает еще один уровень видимости private[this]
.
class C {
private[this] val lock = new Object()
def method1(): Unit = lock.synchronized {
println("method1")
}
}
Здесь фактически никакой другой объект, отличный от конкретного экземпляра C
, не может получить доступ к lock
. Даже другие экземпляры одного класса не могут получить доступ к lock
.