一.sychronized
sychronized是java中最基本同步互斥的手段,可以修饰代码块、方法、类。 在修饰代码块的时候需要一个reference对象作为锁的对象。 在修饰方法的时候默认是当前对象作为锁的对象, 在修饰类时候默认是当前类的Class对象作为锁的对象。
synchronized会在进入同步块的前后分别形成monitorenter和monitorexit字节码指令。在执行monitorenter指令时会尝试获取对象的锁,如果此没对象没有被锁,或者此对象已经被当前线程锁住,那么锁的计数器加一,每当monitorexit被锁的对象的计数器减一,直到为0就释放该对象的锁。由此synchronized是可重入的,不会出现自己把自己锁死。
二.ReentrantLock
以对象的方式来操作对象锁.相对于sychronized需要在finally中去释放锁
三.synchronized和ReentrantLock的区别
除了synchronized的功能,多了三个高级功能: 等待可中断、公平锁、绑定多个Condition。
1.等待可中断
在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待。
tryLock(long timeout, TimeUnit unit)
2.公平锁
按照申请锁的顺序来一次获得锁称为公平锁。synchronized的是非公平锁,ReentrantLock可以通过构造函数实现公平锁。
new RenentrantLock(boolean fair)
3.绑定多个Condition
通过多次newCondition可以获得多个Condition对象,可以简单的实现比较复杂的线程同步的功能。通过await(),signal();
总的来说,lock更加灵活。
主要相同点:
Lock能完成synchronized所实现的所有功能
不同点:
1.ReentrantLock功能性方面更全面,比如时间锁等候,可中断锁等候,锁投票等,因此更有扩展性。在多个条件变量和高度竞争锁的地方,用ReentrantLock更合适,ReentrantLock还提供了Condition,对线程的等待和唤醒等操作更加灵活,一个ReentrantLock可以有多个Condition实例,所以更有扩展性。
2.ReentrantLock必须在finally中释放锁,否则后果很严重,编码角度来说使用synchronized更加简单,不容易遗漏或者出错。
3.ReentrantLock 的性能比synchronized会好点。
4.ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁,而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以更容易产生死锁。
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/7577.html