问一个并发问题,synchronized关键字未能保证线程代码块同步

synchronized关键字未能够保证线程同步
首先,我的测试代码如下:

package test;

public class CommenTest {

    public static Integer a = 10;

    public static void main(String[] args) {
        Runnable run = (() -> {
            for (int i = 0; i < 1000000; i++) {
                synchronized (a) {
                    a++;
                    System.out.println(a);
                }
            }
        });

        Thread thread1 = new Thread(run);
        Thread thread2 = new Thread(run);

        thread1.start();
        thread2.start();

        System.out.println(a);
    }

}

然后,我在第9行和第23行这里打断点,使得程序停止,接着我选中线程1和线程2然后点击Resume按钮让这两个线程同时开始执行,并执行完毕,如下图
图片说明
最后我发现结果并不是预期的2000010,而是一个比这要小的数字,而且多次执行基本没有一次是正确结果,如下图
图片说明
不知道这是什么原因,希望帮忙解答一下

因为这里的a是在变化的值,你的锁都发生变化了,当然就锁不住了。关键是在-128-127之间,Integer都是会做缓存的

public class Test {
public static volatile Integer a = 10;
public static void main(String[] args) {

        Runnable run = (() -> {
            for (int i = 0; i < 1000; i++) {
                synchronized (a) {
                    a++;
                    System.out.println(a);
                }

            }
        });

        Thread thread1 = new Thread(run);
        Thread thread2 = new Thread(run);

        thread1.start();
        thread2.start();

        System.out.println(a);
        }
}

public class Test {
public static  Integer a = 10;
public static void main(String[] args) {

        Runnable run = (() -> {
            for (int i = 0; i < 1000; i++) {
                synchronized (a) {
                    a++;

                }
                System.out.println(a);
            }
        });

        Thread thread1 = new Thread(run);
        Thread thread2 = new Thread(run);

        thread1.start();
        thread2.start();

        System.out.println(a);
        }
}

将楼主的代码稍微改动了一下 ,以上两种改动执行结果完全一致 所以我觉得是因为代码进行了重排序导致上述问题的出现 , a++ 属于非原子性操作, synchronized 锁住的也是a ,当a 计算完毕之后synchronized 认为保证原子性操作的任务已经完成,所以为了执行效率, 代码进行了重排序的操作 (个人猜测,如有不对,欢迎各位大佬指正)

多线程同步是有前提的:必须保证多个线程用的是同一把锁(只要 synchronized(obj){} 中的对象obj不同,就是不同的锁,不同的锁就是不同的同步)。

synchronized 锁住的对象是 a,而 a 又是不断变化的, 相当于线程1和线程2 的锁是不同的,线程1和线程2进入了不同的同步,当然就会发生线程安全问题。

二楼完全跑偏了。

锁要相同吧,一般都是当前对象