synchronized原理
synchronized是自适应的,会根据情况产生锁膨胀/锁升级过程
在加锁时会经历几个阶段
- 无锁(就是没加锁)
- 偏向锁
- 轻量级锁
- 重量级锁
偏向锁
偏向锁可以类比于单例模式的懒汉模式,在用到的时候才加锁,节省开销。
只是标记了这个锁是我的了,实际上还没上锁,直到有其他线程来竞争锁,才会真正的加锁
轻量级锁
当别的线程开始竞争锁,进入轻量级锁(自适应的自旋锁)
具体可见:http://t.csdn.cn/rINyd
重量级锁
当锁竞争激烈的时候,就会碰撞到重量级锁,也就是系统提供的mutex
synchronized的优化(重点)
**锁消除:**编译器会判断当前的锁是否可以消除,如果可以就直接删掉
例如StringBuffer的append方法都是带有synchronized的,但如果编译器发现该代码不是在多线程环境中执行的,就会把锁删去,节省成本
锁粗化:
锁粒度大小:就是作用范围,锁粒度就大,并发效率就越低。作用范围小,锁粒度就小,并发效率就搞。
锁粗话就是增大锁粒度,增大作用范围,减少上锁和释放的次,提高效率
比如以下代码:
for(...) {
synchronized(lock) {
n++;
}
}
每次循环一次都要加锁释放锁拉低了效率
编译器就会自动将锁粗化
synchronized(lock) {
for(...) {
n++;
}
}
这样就只用上一次锁