Synchronized

原理:

JVM是通过进入,退出对象监视器(Monitor)来实现同步,而对象监视器的本质是底层的操作系统的互斥锁(Mutex Lock)

具体实现是在编译之后在同步方法调用前加入一个monitor.enter指令,在退出方法和异常处插入monitor.exit的指令。对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程monitor.exit之后才能尝试继续获取锁。

Synchronized的四种状态无锁,偏向锁,轻量级锁,重量级锁分别解释一下

  • 无锁
    当一个线程刚刚拿到锁使用CAS来判断是否出现冲突而顺利执行就是无锁状态。

  • 偏向锁
    当这个线程不断请求这一把锁,这个锁变为偏向锁。当一个线程访问同步代码块只有在遇到其他线程尝试竞争偏向锁时持有偏向锁的线程才会释放锁,线程不会主动去释放偏向锁。

  • 适应性自旋
    在使用CAS时,如果操作失败,CAS会自旋再次尝试。由于自旋
    是消耗CPU,所以jdk1.6加入了适应性自旋,即如果某个锁自旋很少成功获得,那么下一次就会减少自旋。

  • 轻量级锁
    当出现另一线程竞争此锁,就转为轻量级锁。因为竞争锁对象的线程不多,而且线程持有锁的时间也不长。因为阻塞线程需要CPU从用户态转为内核态代价太大。所以干脆不阻塞而是自旋等待锁释放。
    轻量级锁的获取和释放依赖多次CAS原子指令,而偏向锁只需要在置换ThreadID的时候依赖一次CAS操作。

  • 重量级锁
    如果此时一个线程占用该锁,一个在CAS自旋,此时又进来第三个线程来竞争这个锁对象,那么这个轻量级锁会膨胀为重量级锁。重量级锁除了拥有锁的线程都阻塞,防止CPU空转。锁可以升级不能降级。但是偏向锁是可以被重置为无锁状态的。

锁消除:在某段代码即将第一次被执行时进行编译(JIT编译,即时编译),通过对上下文的扫描,经过逃逸分析,去除不可能存在共享资源竞争的锁就叫消除锁,节省了无意义的请求锁时间。

锁粗化:同步块越小越好,为了缩短阻塞时间。将多个连续的加锁解锁操作连接在一起形成一个范围更大的锁,避免频繁的加锁解锁操作。

你可能感兴趣的:(Synchronized)