Подтвердить что ты не робот

Какой объект я могу синхронизировать в 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...

Не могли бы вы дать мне понять это?

4b9b3361

Ответ 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.