synchronized工作过程中,具体讨论下synchronized里面都干了啥??
- 开始是乐观锁,如果锁冲突频繁,就转化为悲观锁
- 开始时候轻量级锁实现,如果锁被持有的时间较长,就转换为重量级锁
- 实现轻量级锁的时候,大概率用到的自旋锁策略
- 是一种不公平锁
- 是一种可重入锁
- 不是读写锁
synchronized的关键策略:锁升级~
偏向锁:只是先让线程针对锁,做个标记(做个标记很快的,非常轻量)
如果整个代码执行过程中都没有遇到别的线程和竞争这个锁,此时,就不用真的加锁了,但是,一旦要有了别的线程尝试来竞争这个锁!于是偏向锁就立即升级成真正的锁(轻量级锁),此时,别的线程只能等待,既保证了效率,又保证了线程安全!!
锁消除:编辑阶段,做的手段
检测当前代码是否是多线程执行/是否有必要加锁??如果无必要,又把锁给写上了,就会在编译过程中自带把锁去掉!!
如:synchronized不应该被滥用!
StringBuilder与StringBuffer中:StringBuffer是线程安全的!!
对StringBuffer而言,把关键的方法都加了synchronized关键字!!
但是,如果单线程使用StringBuffer,不涉及线程安全问题,但是synchronized是不是也写了??相当于加锁操作,没有真正被编译!!
不是说写了synchronized就一定线程安全
也不是说,不写synchronized就一定线程不安全
这得看具体的代码了!
锁粗化
锁的粒度:synchronized代码块,包含代码的多少(代码越多,粒度越粗,代码越少,粒度越细)
一般写代码的时候,多数情况下,是希望锁的粒度更小一点(串行执行的代码少,并发执行的代码就多),但是,如果某个场景要频繁的加锁/解锁,此时编辑器就可以把这个锁优化成一个更粗粒度的锁!!
每次的加锁/解锁,都要有开锁,尤其是每次释放锁之后,重新加锁,还需要重新竞争。
举列:
上班之后:向领导汇报工作(领导给安排三个工作:ABC)
1.先打电话,汇报工作A的进程,挂了电话;
再打电话,汇报工作B的进程,挂了电话;
再打电话,汇报工作C的进程,挂了电话;
打电话给领导,领导就干不了别的了,别人给领导打电话就得阻塞等待!!
每次锁竞争都可能引起一定的等待开锁,此时整体的效率可能降低!!
2.打一个电话,汇报ABC的工作,挂了电话~~