多线程 - synchronized 和 ReentrantLock的区别
标签: java基础 多线程
synchronized
和ReentrantLock
都是多线程中的上锁操作,目的是使程序互斥执行,从而保证对资源的访问是线程安全的。
1. 使用方法
synchronized
是一个关键字,可以修饰方法、语句块。但ReentrantLock
是一个类,使用时必须在用户类中组合实现这个类,并调用lock()
,unlock()
等方法来控制。
2. 锁定机制
ReentrantLock
拥有锁投票,定时锁等候和中断锁等候等机制。
例如:线程A和B都要获取对象Obj的锁定,假设A获取了对象Obj锁,B将等待A释放对Obj的锁定。
使用synchronized
,如果A不释放,B将无限阻塞直到A释放锁;
使用ReentrantLock
,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情。
3. 锁定释放
synchronized
是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized
的锁定,而且在代码执行时出现异常,JVM会自动释放锁定;但是ReentrantLock
则不行,它是通过代码实现锁定的,要保证锁一定会被释放,就必须将unLock()
放到finally{}
中。
4. 性能对比
synchronized
编译器会优化,可读性好,资源宽松时性能也不错,但缺点资源竞争激励时性能太差,能下降几十倍。ReetrantLock
类性能稳定,控制灵活,但复杂性也相应提高,一般优化时才会用到。
5. 附: ReentrantLock
四种锁定方法
a) lock()
: 如果获取了锁,立即返回,如果别的线程正持有锁,当前线程则一直处于休眠状态,直到获取锁(与synchronized
等价);
b) tryLock()
: 如果获取了锁,立即返回true,如果别的线程正持有锁,立即返回false。利用这一特性,可以终止等待先干别的;
c) tryLock(long timeout,TimeUnit unit)
: 如果获取了锁,立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁,就返回true,如果等待超时,返回false;
d) lockInterruptibly()
: 如果获取了锁,立即返回,如果没有获取锁定,当前线程处于休眠状态,直到获得锁,或者当前线程被别的线程中断。