Synchronized从使用到原理
为JVM提供,有很多优化,Lock锁为JDK提供。
Java中锁的概念
同步关键字synchronized
- 用于实例方法,静态方法时,隐式指定对象锁;
- 用于代码块时,显示指定对像锁;
- 锁的作用域:对象锁,类锁,分布式锁;
- 引申:多个线程怎么办?
特性:synchronized是悲观锁,排他锁(独享锁),可重入锁,非公平锁
锁优化:锁消除(开启锁消除的参数: -XX:+DoEscapeAnalysis -XX:+EliminateLocks)
锁粗化:JDK做了锁粗化的优化,但我们自己可从代码层面优化
Synchronized和Volatile的比较:
- Synchronized保证内存可见性和操作的原子性
- Volatile只能保证内存可见性
- Volatile不需要加锁,比Synchronized更轻量级,并不会阻塞线程(volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞)
- volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化(如编译器重排序的优化)
- volatile是变量修饰符,仅能用于变量,而synchronized是一个方法或块的修饰符
- volatile本质是在告诉JVM当前变量在寄存器中的值是不确定的,使用前,需要先从主存中读取,因此可以实现可见性。而对n=n+1,n++等操作时,volatile关键字将失效,不能起到像synchronized一样的线程同步(原子性)的效果。
轻量级锁
锁升级后->重量级锁 JVM修改对象头
偏向锁
锁的升级过程
总结:
- 抢锁使用CAS操作,先比对人后进行修改,比对和修改都需要是原子操作(本质,使用CAS操作对内存进行修改,修改成功即为抢到锁)
- 偏向锁为极端优化,不多做赘述
- 轻量级锁:不停的使用CAS对内存操作,操作成功的即为抢到了锁,未成功的继续CAS自旋
- 重量级锁:owner拥有者,所有线程来抢锁,使用CAS操作来修改owner,未成功的线程进入EntryList中,将线程挂起,然后再次尝试(排队机制)