0

Java のAtomicIntegerArrayをモデルにしたメモリクリティカルなアプリケーションには AtomicByteArray が必要です。私の実装では、4 バイトを整数にラップし、AtomicIntegerArray を使用しています。

get()実装は自明であり、実装set()はかなり簡単です。はcompareAndSwap()よりトリッキーです。私の実装を以下に示します (シングルスレッドで問題なく動作します)。

競合状態を特定しようとしています。get()考えられるシナリオの 1 つは、との呼び出しの間で値が変更され、元に戻されることですcompareAndSet()が、これは無害に見えます。

うまくいかない可能性のあるものを見逃していますか?

/**
 * Atomically sets the element at position {@code i} to the given
 * updated value if the current value {@code ==} the expected value.
 *
 * @param i the index
 * @param expect the expected value
 * @param update the new value
 * @return true if successful. False return indicates that
 * the actual value was not equal to the expected value.
 */
public boolean compareAndSet(final int i, final byte expected, final byte val) {
    int idx = i >>> 2;
    int shift = (i & 3) << 3;

    while (true) {
        final int num = this.array.get(idx);
        // Check that the read byte is what we expected
        if ((byte)(num >> shift) != expected) {
            return false;
        }
        // If we complete successfully, all is good
        final int num2 = (num & ~(0xff << shift)) | ((val & 0xff) << shift);
        if ((num == num2) || this.array.compareAndSet(idx, num, num2)) {
            return true;
        }
    }
}

更新:以下の回答の改善を統合したAtomicByteArrayの基本バージョンを実装しました。

4

1 に答える 1

1

マスクの使用を検討してください。これはより速く/よりきれいかもしれません。

int idx = i >>> 2;
int shift = (i & 3) << 3;
int mask = 0xFF << shift;
int expected2 = (expected & 0xff) << shift;
int val2 = (val & 0xff) << shift;

while (true) {
    final int num = this.array.get(idx);
    // Check that the read byte is what we expected
    if ((num & mask) != expected2) return false;
    // If we complete successfully, all is good
    final int num2 = (num & ~mask) | val2;
    if ((num == num2) || this.array.compareAndSet(idx, num, num2)) {
        return true;
    }
}

競合が発生した場合にできるだけ早く再試行できるように、ループ内で最小限の作業を実行する必要があります。

num == num2痛い以上に役立つかどうかはわかりません。比較せずに試してみることをお勧めします。

于 2014-06-13T19:51:27.570 に答える