https://www.cnblogs.com/54chensongxia/p/11910681.html

原子操作的相关内容参考以上链接。

写了个Demo如下:


    static volatile Integer couter = 0;
    static volatile AtomicInteger integer = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        List<Thread> list = new ArrayList<>();

        for(int i = 0 ; i < 10000 ; i++){
            list.add(new Thread(() -> {
                integer.addAndGet(1);
                synchronized (couter){
                    couter++;
                }
            }));
        }

        for(Thread t : list){
            t.start();
        }
        for(Thread t : list){
            t.join();
        }
        System.out.println(couter);
        System.out.println(integer.get());
    }

因为couter++已经加了同步锁,但count的结果依然不正确,运行结果如下:

9997
10000

结论:

因为synchronized (couter)锁的是couter的地址,当couter的值超过127时,couter会使用新Integer对象的地址,导致之前的锁失效。

正确写法:


    static volatile Object lock = new Object();
    static volatile Integer couter = 0;
    static volatile AtomicInteger integer = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        List<Thread> list = new ArrayList<>();

        for(int i = 0 ; i < 10000 ; i++){
            list.add(new Thread(() -> {
                integer.addAndGet(1);
                synchronized (lock){
                    couter++;
                }
            }));
        }

        for(Thread t : list){
            t.start();
        }
        for(Thread t : list){
            t.join();
        }
        System.out.println(couter);
        System.out.println(integer.get());
    }

运行结果:

10000
10000