volatile 靠的是内存屏障

synchronized 关键字底层是通过 monitorenter 和 monitorexit 实现的,而这两个指令又是通过 lock 和 unlokc 实现的

而lock和unlock在Java内存模型中是必须满足下面四条规则的

原子性: 通过规则一,我们知道对于lock和unlock之间的代码,同一时刻只允许一个线程操作。所以保证了原子性。

可见性: 通过规则一、二、四,可以得出,每次lock和unlock时,都会从内存加载变量或把变量刷新回内存,而lock和unlock之间的变量是不会被其他线程修改的(规则一:同一时刻只允许一个线程)。所以保证了可见性

有序性: 通过规则一、三,我们知道所有对变量的加锁都要排队进行,且其它线程不允许解锁当前线程锁定的对象,所以,synchronized是具有有序性的。

https://eliasyaoyc.github.io/blog/synchronized-的实现原理/