目录
synchronized的几个重要机制
①锁升级(偏向锁)
②锁消除
③锁粗化
锁升级(偏向锁)
并非真正加锁,而只是做了一个标记,减少锁释放的消耗
而当锁冲突出现的适合,偏向锁就会升级为轻量级锁,此时才是真正加锁了
这样既可以保证线程安全,又能够保证效率
偏向锁的核心思想:”懒汉模式“,能不加锁,尽量不加锁,加锁意味着有开销
举个栗子:
一个女生与一个男生a交往,一段时间后女生喜欢上另外一个男生b,此时要和男生a分手,就要想办法、消耗时间(低效)
而如果女生只是与男生a暧昧,一段时间后有喜欢上男生b,此时只需要停止与男生a的暧昧,直接与男生b在一起(高效)
如果在暧昧过程中,有另外一个女生2出现了,也喜欢这个男生,女生1受到威胁(锁竞争),女生1立刻与男生确立关系(真正加锁)
锁消除
编译器的一种优化手段
编译器自动对你加锁的代码做出判定,如果觉得这个场景不需要加锁,就会自动吧synchronized给优化掉
编译器只会在非常有把握的时候进行锁消除(概率小)
StringBuilder 不带有synchronized
StringBuffer 带有synchronized
如果在单线程中使用StringBuffer,编译器就会自动把synchronized优化掉
偏向锁在运行时(运行过程中多线程的调度情况不同)
锁消除在编译阶段
锁粗化
锁的粒度:synchronized里头,代码越多,就认为锁的粒度越粗
粒度细的时候,能够并发执行的逻辑更多,更利于充分利用多核cpu资源
但如果粒度细的锁被反复加锁解锁,会涉及到反复的锁竞争,效率也不高