文章目录
- synchronized和lock的区别
- 公平锁和非公平锁
- 可重入锁
synchronized和lock的区别
-
synchronized 是java的一个关键字,源码在 jvm 中,用 c++ 语言实现,synchronized在发生异常时会自动释放占有的锁,因此不会出现死锁。
-
Lock 是接口,源码由 jdk 提供,用 java 语言实现,不会主动释放占有的锁,必须手动来释放锁,可能引起死锁的发生。
-
功能层面
二者均属于悲观锁、都具备基本的互斥、同步、锁重入功能.Lock 由java语言实现,所以比 synchronized 功能全,例如:
1.几个线程争抢锁时,一个线程成功了,其他几个线程失败了,这时用lock锁可以获取争抢lock锁失败处于阻塞状态的线程。
2.Lock锁提供公平锁和非公平锁,synchronized只提供非公平锁。(非公平锁可以插队,所以效率更高)
3.Lock锁有多个等待队列,snychronized只有一个等待队列。
Lock.newCondition(“c1”),Lock.newCondition(“c2”);
等待队列c1,c1.await(),让线程·进入等待队列c1,c1.signal()唤醒队列中一个线程。
4.Lock 有多种实现实现,如 ReentrantLock(可重入锁), ReentrantReadWriteLock(可重入读写锁)允许多个线程同时进行读操作,而只有在没有任何读操作时才会进行写操作。
5.可打断、可超时 -
性能层面
- 在没有竞争时,synchronized 做了很多优化,如偏向锁、轻量级锁,性能不赖
- 在竞争激烈时,Lock 的实现通常会提供更好的性能
公平锁和非公平锁
公平锁:多个线程去请求锁时,会按照请求锁的顺序去一一获取锁(线程会按顺序进入队列,队头线程获取锁)
优点:所有的线程都能得到资源,不会饿死在队列中。
缺点:cpu需要不停的唤醒被阻塞的线程,吞吐量会下降很多。
非公平锁:在一个合适的时机,允许后请求的线程直接去获取锁,
假设,线程5去获取一把锁时,线程1刚好释放锁,这时线程5就能直接插队,线程5获取不到锁,才会进入等待队列。这样做线程5既可以不用进入队列被唤醒,也可以直接省去线程2被唤醒的时间。(线程5执行时,这个时间唤醒线程2)。
优点:cpu不必唤醒所有线程,整体的吞吐率会提高,
缺点:有些线程一直获取不到锁,会被饿死。
可重入锁
可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。