Как получить AtomicReferenceFieldUpdater из сопутствующего объекта Scala? - PullRequest
5 голосов
/ 07 апреля 2011

Если у меня есть связанный узел в некоторой структуре коллекции, я не хочу, чтобы его следующая ссылка была AtomicReference (мне нужно обновление Atomic CAS), поэтому я объявляю его как:

@volatile var next: Node[A] = _n

, а затемв сообщении объявляют:

val updater = AtomicReferenceFieldUpdater.newUpdater(classOf[Link[_]], classOf[Node[_]], "n")
def cas[A](target: Link[A], old: Node[A], newNode: Node[A]) = updater.compareAndSet(target, old, newNode);

Во время выполнения я получаю следующую ошибку:

java.lang.RuntimeException: java.lang.IllegalAccessException: 
  Class concurrent.Link$ can not access a member of class concurrent.Link
  with modifiers "private volatile"
    at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl.<init>(AtomicReferenceFieldUpdater.java:189)
    at java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdater.java:65)
    at concurrent.Link$.<init>(Link.scala:106)
    ...

Итак, во время выполнения объект-компаньон concurrent.Link$ не concurrent.Link и другой классне может получить доступ к закрытому члену другого.

НО, если я javap -p concurrent.Link

, я получаю:

Compiled from "Link.scala"
public final class concurrent.Link implements concurrent.Node,scala.ScalaObject,scala.Product,java.io.Serializable{
private final java.lang.Object value;
private volatile com.atlassian.util.scala.concurrent.Node node;
public static final boolean cas(com.atlassian.util.scala.concurrent.Link, com.atlassian.util.scala.concurrent.Node, com.atlassian.util.scala.concurrent.Node);
public static final java.util.concurrent.atomic.AtomicReferenceFieldUpdater updater();

Итак, у меня есть все, кроме статического экземпляраAtomicReferenceFieldUpdater объявлено в моем Link классе.

Вопрос в том, как мне получить экземпляр AtomicReferenceFieldUpdater в Scala, который указывает на переменную переменную?

Единственный способ, которым яДо сих пор мы обнаружили, что должны вернуться к Java (реализовать AbstractLink со следующим полем Node и статическим AtomicReferenceFieldUpdater) и наследовать от него, что ужасно.

Ответы [ 2 ]

4 голосов
/ 07 апреля 2011

Hard.Поскольку Scala делает поля частными и доступны только методы доступа, это может быть невозможно.

При этом я в конечном итоге решил сделать это, создав базовый класс Java с изменяемым полем и обновив его там.

Java-файл:

public class Base {
   volatile Object field = null;
}

Scala-файл:

class Cls extends Base {
  val updater = AtomicReferenceFieldUpdater.newUpdater(classOf[Base[_]], classOf[Object[_]], "field")
  def cas[A](old: Object, n: Object) = updater.compareAndSet(this, old, n);
}

У меня не было другого подхода.

0 голосов
/ 27 мая 2011

Мне сказали, что нет способа сделать это в чистом scala, и вам нужно определить класс в Java для этого.К счастью, кросс-компиляция довольно проста, но все же раздражает!

...