synchronized一个有趣现象

发布时间 2023-05-28 18:11:45作者: 云归处、

在学习synchronized时发现了一个有趣的现象:

public class MyThread implements  Runnable {
    private int number=10;
    private  boolean flag = true;
    @Override
    public  void run() {
        while (flag) {
            //同步块,()填变化的量必须是引用类型,锁定的就是传入参数
            synchronized (Integer.valueOf(number)){
                number--;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (number < 1) {
                    flag=false;
                }
                else {
                    System.out.println(Thread.currentThread().getName() + "--" + number);
                }
            }
            }
        }

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        new Thread(myThread,"李").start();
        new Thread(myThread,"马").start();
        new Thread(myThread,"王").start();
    }
}

/*
李--7
马--7
王--7
王--4
李--4
马--4
李--1
马--1
王--1

我以为只有在一个线程执行完同步块后另外一个线程才有机会进入,但上述情况却像是一旦对同步监视器的相关操作(加减乘除)结束后其他线程就已经可以进入同步块了,以至于造成上述情况:李在进入后执行减操作,之后休眠,同时马进入同样执行减操作后休眠,王重复上述操作,在三者都先后执行完休眠操作,但是此时的number却已经被减了三次了使用呈现上述的删除结果

再做一次实验:

public class MyThread implements  Runnable {
    private static Integer number=10;
    private static Integer number1=10;
    private  boolean flag = true;
    @Override
    public  void run() {
        while (flag) {
            synchronized (number){
                if (number < 1) {
                    flag=false;
                }
                else {
                    System.out.println(Thread.currentThread().getName() + "--number--" +number);
                    number--;
                    System.out.println(Thread.currentThread().getName() + "--number1--" +number1--);
                }
            }
            }
        }

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        new Thread(myThread,"李").start();
        new Thread(myThread,"马").start();
        new Thread(myThread,"王").start();
    }
}

/*
李--number--10
李--number1--10
李--number--9
李--number1--9
王--number--9
李--number--8
王--number1--8
李--number1--7
马--number--6
王--number--6
马--number1--6
王--number1--5
马--number--4
李--number--4
马--number1--4
李--number1--3
马--number--2
王--number--2
马--number1--2
王--number1--1

可以看到number出现了多次重复,number1却完全没有。可以看出好像只会在操作同步监视器的那一行上锁一样。我以为只有在一个线程执行完同步块后另外一个线程才有机会进入。这是我的一个误区。同步块中最好还是就写相关的操作吧