you can see that System.identityHashCode(i) changes, so another thread that was waiting outside the synchronized block can now enter it.
but the most important thing,i want to know why another thread has same System.identityHashCode(i) can enter the synchronized block
当i=10时,两个线程竞争synchronized权限,此时监控器对象是Integer(10),然后张三成功开始执行,并且在最后将i的值改为了Integer(9),但是这时候李四在等待的监控器对象仍然是Integer(10),并不会因为张三的i--而改变,所以当张三离开同步代码块后李四进入了监控器对象为Integer(10)的同步代码块,而张三循环回来后重新尝试进入一个同步代码块,此时它需要获取的监控器对象为Integer(9),所以跟李四不构成竞争关系,两个线程同时进入了监控器对象不同的代码块中,并且读取到的新的i值都是9
深层的原因与synchronized关键字的实现原理有关,多个线程竞争同一个监控器对象,其实是都进入了这个对象关联的monitor的entryList,在这里面就是张三李四都进入了Integer(10)的monitor的entryList,所以就算i被张三改为了Integer(9),也不会改变李四的监控器对象