Lock还是Synchronized怎么选

需要加锁的时候是使用Lock还是synchronized关键字

开头先说结论,需要看加的锁是不是需要超时时间,超时没获取到的取消,这种需要使用Lock,Synchronized不支持超时时间的设置,那么其他的呢,
并发量大的时候使用哪个,并发量小的时候使用哪个,并发量大,竞争激烈优先使用Lock,并发量小的可以使用synchronized

synchronized效率问题

关键字是为了保证原子性的,锁的就是对象,具体锁哪个对象取决于使用位置,主动的synchronized(object)这样就是锁的填入的对象,锁标志存在于对象头里面,
关键字还可以加在方法上,加在成员方法上,等同于synchronized(this),锁的就是本实例对象,加在静态方法上,就是锁的类对象,等同于synchronized(this.class)
原理大致是这样,那么效率问题是怎么说,synchronized之前 加锁原理就是通过底层的monitor enter和monitor exit来进行加锁和释放锁,涉及到系统层面调用,
比较重,在切换的时候耗费较多,后来synchronized 有进行优化效率,引入了几种状态,无锁,偏向锁,轻量级锁,重量级锁,也就是最开始是无锁状态,
有线程使用的时候变为偏向锁,这时候只有一个线程,无竞争,会把对应的线程id存起来,发现线程是偏向的线程就不需要进行再加锁,提高效率,
当第二个线程,第三个线程过来的时候,发现偏向锁的线程id不是自己,就需要加锁,这时候进行cas加锁,尝试一定的次数,这时候如果cas加锁成功,
变为轻量级锁,如果没加锁成功升级为重量级锁,即原来的需要系统调用来加锁。

小问题

轻量级锁即然效率高为啥要升级?
答:因为竞争不到锁如果还一直进行cas,造成cpu空转,浪费资源,也达不到高性能的场景,升级为重量级锁进入等待队列,等前面执行完了,系统执行这个

Lock 原理,为什么可以适应高并发

上面说了synchronized的原理,讲到了轻量级锁使用的cas来进行加锁,效率比较高,但是如果一直空转也不行,需要进入等待队列等待,Lock就处理了这个问题,
Lock的都是基于AQS的工具类进行实现的,AQS底层加锁原理就是cas,cas失败之后,提供了一个双向队列,等同于synchronized的等待队列,等前面执行完,
唤醒自己,AQS前面也有分析过,不进行重复分析,那么很明显,Lock的优势就在于cas获取比较轻量,然后也存在等待队列,让线程休眠,不一直占用cpu,
采用的LockSupport.park方法让线程休眠,LockSupport.unpark 唤醒线程,主要是这里的切换比synchronized轻

总结

Lock更加适合高并发的情况,因为synchronized虽然进行了优化,但是这个锁升级的过程,在遇到高并发的时候都会升级成重量级锁,跟原来没太大的差别,
Lock的性能不随着并发的增高明显降低,更加适应高并发的情况,在竞争度比较低的时候synchronized因为存在偏向锁,偏向锁的效率基本接近无锁,
效率也比较高。

你可能感兴趣的:(JAVA,java,jvm,锁,Lock,Synchronized)