synchronized的偏斜锁,轻量级锁,重量级锁
有关synchronized锁升级的理念,很多博客讲的很明白,在这里我将我个人的理解讲述一下,方便各位的理解,如果有描述的不正确的地方还请多多指正,不胜感激。
synchronized 是 Java 内建的同步机制,所以也有人称其为 Intrinsic Locking,它提供了互斥的语义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能等待或者阻塞在那里。
synchronized重在哪里?
JDK1.6之前,使用synchronized来添加同步操作的话,synchronized会直接锁上睁个代码块,当一个线程访问来加锁的资源时。其他的所有线程会进入堵塞队列中堵塞。完事在一个一个的唤醒。而将线程堵塞和唤醒这个操作是需要操作系统的帮助,需要进行用户态到内核态的切换。操作系统这个操作是非常慢的,重即重在这里。
JDK1.6之后synchronized发生了什么变化?
JDK1.6之后,整个synchronized操作会根据并发的情况来逐步的进行锁升级。
偏斜锁(偏向锁)
如果被synchronized同步的对象,一直只有同一个线程来访问。
那么会将这个线程id保存到这个对象的对象头中,具体保存到对象头中的一个叫做MarkWord的部分。表示对象偏向于这个线程。以后这个线程再来的话,一看到对象头中有自己的线程id就会自动放行。这就是偏向锁。
轻量级锁
在偏斜锁的情况下,如果有另一个线程也想访问被synchronized同步的对象。那么线程会通过CAS的方式来尝试将自己的线程id写入到刚刚那个MarkWord中,如果写入成功了,就会成功获取锁。
重量级锁
刚刚CAS写入的时候不成功会进行多次自旋,当超过一定次数,就会最终升级成重量级锁,这个时候的操作就和早期jdk的synchronized一样了,此时会调用操作系统的互斥锁。当前线程会被阻塞住。
参考
synchronized底层如何实现?什么是锁的升级、降级?: 链接.