存在层次上:
1、synchronized:Java 的关键字,在 jvm 层面上
2、Lock:是一个接口
锁的释放:
synchronized:
1、以获取锁的线程执行完同步代码,释放锁
2、线程执行发生异常,jvm 会让线程释放锁
Lock:
1、在finally 中必须释放锁,不然容易造成线程死锁
锁的获取:
1、synchronized:假设A线程获得锁,B 线程等待。如果A线程阻塞,B线程会一直等待
2、Lock:分情况而定,Lock 有多个锁获取的方式,大致就是可以尝试获得锁,线程可以不用一直等待(可以通过 tryLock() 判断有没有锁)
锁的释放(死锁产生):
1、synchronized:在发生异常时候会自动释放占有的锁,因此不会出现死锁
2、Lock:发生异常时候,不会主动释放占有的锁,必须手动 unlock() 来释放锁,可能引起死锁的发生
锁的状态:
1、synchronized:无法判断
2、Lock;可以判断
锁的类型:
1、synchronized:可重入 不可中断 非公平
2、lock:可重入 可判断 可公平(两者皆可)
性能:
1、synchronized:少量同步
2、Lock:大量同步
1、Lock 可以提高多个线程进行读操作的效率。(可以通过 readwritelock实现读写分离)
2、在资源竞争不是很激烈的情况下,Synchronized 的性能要优于 Reetrantlock,但是在资源竞争很激烈的情况下,Synchronized 的性能会下降几十倍,但是ReetrantLock 的性能能维持常态;
3、ReentrantLock 提供了多样化的同步,比如有时间限制的同步,可以被Interrupt 的同步(synchronized 的同步是不能 Interrupt 的)等。在资源竞争不激烈的情形下,性能稍微比 synchronized 差点点。但是当同步非常激烈的时候,synchronized 的性能一下子能下降好几十倍。而 ReentrantLock 确还能维持常态。
调度:
1、synchronized:使用 Object 对象本身的 wait 、notify、notifyAl1调度机制
2、Lock:可以使用 Condition 进行线程之间的调度
用法:
1、synchronized:在需要同步的对象中加入此控制,synchronized 可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
2、Lock:一般使用 ReentrantLock 类做为锁。在加锁和解锁处需要通过lock()和 unlock()显式指出。所以一般会在 finally 块中写 unlock()以防死锁。
底层实现:
1、synchronized:底层使用指令码方式来控制锁的,映射成字节码指令就是增加来两个指令:monitorenter和monitorexit。当线程执行遇到monitorenter指令时会尝试获取内置锁,如果获取锁则锁计数器+1,如果没有获取锁则阻塞;当遇到monitorexit 指令时锁计数器-1,如果计数器为 0 则释放锁。
2、Lock:底层是CAS 乐观锁,依赖AbstractQueuedSynchronizer 类,把所有的请求线程构成一个 CLH 队列。而对该队列的操作均通过 Lock-Free(CAS)操作。
Was this helpful?
0 / 0