一、前言
本文要介绍使用Java5中 Lock 对象,同样也能实现同步的效果,而且在使用上更加方便、灵活,主要包括 ReentrantLock 类的使用和ReentrantReadWriteLock 类的使用。
lock 与 synchronized 关键字的区别?
-
- synchronized 是java内置关键字;Lock是个java类。
- synchronized 会自动释放锁;Lock需在finally中手工释放锁(unlock()方法释放锁)
- synchronized 的锁可重入、不可中断等待、非公平;而Lock锁可重入、可中断等待(利用超时机制)、可公平。
- synchronized 的 wait() 和 notify() 或 notifyAll() 方法可以实现一个隐含的条件。而 Lock锁可以同时绑定多个 Condition 对象。
等待可中断是指当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情,可中断特性对处理执行时间非常长的同步块很有帮助。
在Java 5之前,当一个线程获取不到锁而被阻塞在 synchronized 之外时,对该线程进行中断操作,此时该线程的中断标志位会被修改,但线程依旧会阻塞在synchronized上,等待着获取锁;在Java 5中,AQS 同步器提供了 acquireInterruptibly(int arg) 方法,这个方法在等待获取同步状态时,如果当前线程被中断,会立刻返回,并抛出 InterruptedException。
二、使用ReentrantLock 类
1、在java多线程中,可以使用 synchronized 关键字来实现线程之间同步互斥,但在JDK1.5中新增加的 ReentrantLock(重入锁) 也能达到同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路分支通知等功能,而且在使用上也比 synchronized 更加的灵活。
2、调用lock.lock()代码的线程就持有了“对象监视器”,即lock 持有的是对象锁,依赖于该类的实例存在。
public class MyService { private Lock lock=new ReentrantLock(); public void testMethod(){ lock.lock(); for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+(i+1)); } lock.unlock(); } }