ローカルAtomicReferenceとラムダの配列

UFO少年アブドラジャン:

私は変更をしようとすると、ラムダとローカル変数を取得します。私が使用する必要があります知って効果的に最終ラムダのローカル変数のために。私は失敗した変更ローカル変数AtomicReferenceを使用する場合:

    public class Lamb {
    public static void main(String[] args) throws InterruptedException {
        Lamb lamb = new Lamb();
        GlobalL globalL = new GlobalL();
        lamb.a(globalL);
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                globalL.printSum();
            }).start();
        }
        Thread.sleep(3000);
        System.out.println("--------After Work--------");
        globalL.printSum();
    }
    public void a(GlobalL globalL) {
        AtomicReference<Integer> number = new AtomicReference<>(0);
        Work work = () -> {
            number.getAndSet(number.get() + 1);
            return number.get();
        };
        globalL.setWork(work);
    }
}
class GlobalL {
    private Work work;
    public void printSum() {
        System.out.println(work.getAndInc());
    }
    public void setWork(Work work) {
        this.work = work;
    }
}
interface Work {
    int getAndInc();
}

出力異なるたびに:

  1. -------- --------仕事の後に
    97
  2. -------- --------作業後
    99
    私は配列にこの作業罰金をアトミックに変更します。
public void a(GlobalL globalL) {
        Integer[] number = {1};
        Work work = () -> {
            number[0]++;
            return number[0];
        };
        globalL.setWork(work);
}

出力毎回:
-------- --------仕事の後
102

  1. 何がアレイと、原子このような状況で起こっているの?
  2. 非最終ローカル変数で匿名クラスとlabmdaを仕事にする方法?
  3. どのJVMは、ラムダで動作しますか?
オイゲンCovaci:

1)コード:

 number.getAndSet(number.get() + 1);
 return number.get();

アトミックに実行されていない操作のカップルがあるので、クリティカルセクションです。あなたは異なる結果を得る理由です。クリティカルセクションを解消するには:

public void a(GlobalL globalL) {
    AtomicInteger number = new AtomicInteger(0);
    Work work = () -> {
        return number.incrementAndGet();
    };
    globalL.setWork(work);
}

2)あなたは(見ることができないこのまたは匿名クラスの公式チュートリアル

3)IMO、それは別の問題でなければなりません。いくつかの言葉でそれを置くために、ラムダは単なるシンタックスシュガーであり、彼らは匿名内部クラスにコンパイルされます。


why array works correctly?質問、答えは:それはしていません。同じ理由++アトミック演算子ではない だけ、のは、1000年と言うようにするスレッドの数を増やし、それを証明するには:

   for (int i = 0; i < 1000; i++) {
        new Thread(() -> {
            globalL.printSum();
        }).start();
    }

私は取得しています:

-------- --------仕事の後972

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=8235&siteId=1