1.了解Synchrozied
Synchrozied是一种悲观锁,通过Synchroized实现同步机制,在操作数据时,判断该对象是否被锁定,如果被锁定则进入阻塞状态直到被占用的线程释放,如果没有被锁或者当前线程已经存在操作对象的锁则进行上锁操作,操作完成之后在进行释放锁;
当一个类对象被锁时,被Synchrozied修饰的方法将产生阻塞,非Synchroized修饰的方法不会产生阻塞。Synchroized通过可重入性解决自身锁死的情况;因为他是通过判断对象没有锁或者当前对象的锁来进行加锁,如果没有重入性,一类中两个同步方法互相调用就会造成死锁。
Synchroized也是一种非公平锁,因为他不会按照申请的时间来分配锁,而是通过竞争的形式来获取锁,这样提高了执行的性能;
- 方法锁:synchronized修饰方法时,每个实例对象对应一把锁。
- 对象锁:synchronized修饰方法或代码块,每个实例对象对应一把锁。
- 类锁:synchronized修饰静态方法或者静态代码块,所有的实例对象共用同一把锁,我们称之为类锁。
2.Synchronized的锁升级过程
Synchroized锁升级过程:由低到高分别为->偏向锁,轻量级锁,重量级锁;
升级锁的必要性:在一个线程多次获得同一个锁的情况下,如果每次都要竞争锁会增大很多没有必要的代价,为了降低CPU的开销,提供了执行效率。升级锁的实现,依赖于对象头中的Mark Word,里面会记录当前第一个获取锁的线程ID,以及锁的状态;
偏向锁:当一个线程A抢到锁之后,将线程A的ID记录在对象头中,并且锁升级为偏向锁;后续线程A再次获取该对象的锁时,发现对象处于偏向锁状态,对象头中的线程ID与线程A一致,此时会直接获取到偏向锁;
轻量级锁:当另外一个线程B获取锁时,发现锁一级处于偏向锁状态,此时线程B会用过CAS的方式尝试性争抢锁【修改对象头中的线程ID】(判断线程A是否存活,存活就不能进行修改),如果偏向锁抢锁失败,择偏向锁就升级为轻量级锁,如果抢锁成功则执行代码;
重量级锁:轻量级锁时通过自旋的方式争抢锁,并且适用于线程持有锁的时间不长的情况下(因为阻塞线程需要进行CPU状态,代价太大,所以自旋),当线程的自旋次数超过阈值(默认情况下是10)的时候为了防止cpu空转,会将自旋锁升级为重量级锁,并且将没有获取锁的线程进行阻塞;
轻量级锁获取锁修改线程ID的方式:偏向锁升级为轻量级锁之后,线程B将锁对象的markword拷贝到线程本身的markword空间中,然后通过CAS的方式去设置锁对象中的线程ID值;