5

いくつかのコレクション構造にリンクされたノードがある場合、その次のリンクをAtomicReference(アトミック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に戻って(次のNodeフィールドとstaticを使用してAbstractLinkを実装するAtomicReferenceFieldUpdater)、そこから継承することです。これは醜いです。

4

2 に答える 2

4

難しい。Scalaはフィールドをプライベートにし、アクセサーメソッドのみを使用できるようにするため、これは不可能な場合があります。

これを行うとき、私は最終的に、volatileフィールドを使用して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);
}

私は別のアプローチを思い付いていません。

于 2011-04-07T18:48:24.500 に答える
0

純粋なscalaでこれを行う方法はないと言われています。これを行うには、Javaでクラスを定義する必要があります。幸いなことに、クロスコンパイルは非常に簡単ですが、それでも面倒です。

于 2011-05-27T05:54:07.290 に答える