StringBuffer在单线程和多线程环境中的区别

这道题重点在synchronized的四种锁的状态,分别为:无锁状态,偏向锁状态,轻量级锁,重量级锁

因为StringBuffer是synchronized保证线程安全的,单线程下synchronized默认加的是偏向锁,多线程则是加重量级锁

锁膨胀(又称锁升级):

在大多数情况下,锁总是由同一线程多次获得,不存在多线程竞争,所以出现了偏向锁。其目标就是在只有一个线程执行同步代码块时能够提高性能。

当一个线程访问同步代码块并获取锁时,会在Mark Work(对象头)中存储锁偏向的线程ID.在线程进入和退出的时候不需要CAS加锁和解锁,而是检查MarkWord里是否存储着指向当前线程的偏向锁

线程不会主动释放偏向锁,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,判断锁对象是否处于被锁定状态。撤销偏向锁后恢复到无锁(锁标志位为“01”)或轻量级锁(锁标志位为“00”)的状态。

当有其他线程访问同步代码块,偏向锁就会升级为轻量级锁,其他线程通过自旋形式尝试获取锁,不会阻塞,从而提高性能

若当前只有一个等待线程,则该线程通过自旋进行等待。但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁。

升级为重量级锁时,锁标志的状态值变为“10”,此时Mark Word中存储的是指向重量级锁的指针,此时等待锁的线程都会进入阻塞状态。

总结:

偏向锁通过对比Mark Word解决加锁问题,避免执行CAS操作。而轻量级锁是通过用CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。重量级锁是将除了拥有锁的线程以外的线程都阻塞

参考链接:找不到了

猜你喜欢

转载自blog.csdn.net/ailaojie/article/details/88955643