Lock、Synchronized锁区别解析( 六 )

可以看到 ,ReetrantLock 有两个构造方法 , 这也是Lock 实现类通有的 , 我们重点看一下第二种构造器 , 因为第一种的实现代码只不过是第二种构造器中代码的一种 。 参数 fair 表示是否是公平锁?如果是 true, 那么创建的 ReetrantLock 对象就是公平锁对象 , 如果 false 或者没有指定参数那么创建出来的对象都是非公平锁对象 。 而 synchronized 只可能是非公平锁 。
常用方法:下面就以ReentranLock 为例 , 说一下lock的常用实现方法 。
1、Lock()lock() 方法其实和 synchronized 的重量级锁执行策略是一样的 , 当然如果在对象创建时指定公平锁 , 那么会直接进入 “等待队列”, 如果没有指定或者是指定为非公平锁那么会先尝试获取锁资源 。 然后没有获取到就会进行一次上下文切换 。
2、tryLock()尝试获取锁资源 , 获取到就直接执行后面的代码并返回 true , 如果没有获取到直接退出不进入 "等待队列" 并返回 false。
3、tryLock(long time,TimeUnit unit)尝试在一段时间内获取锁资源 , 获取到就执行后面的代码并返回 true , 否则退出返回 false。 可以通过 interrupt() 方法中断阻塞状态 。
4、lockInterruptibly()和 lock()一样 , 只不过可以调用该线程的 interrupt() 方法去中断 , 而 Lock() 方法不会被中断 , 只能获取到锁资源的线程调用了 unlock方法才会中断等待状态 。
同步 , 等待通知模型实现同步实现:lock 的加锁的对象就是 lock 本身的对象 , 所以我们只需要调用 lock()方法就可以实现加锁操作 , 但是与 synchronized 不同的是 lock 锁需要手动的去释放 , 也就是调用 unlock() 方法去释放当前对象的锁 , 所以unlock()方法一般是在 finally 修饰的代码块中 , 防止上面发生异常而没有释放锁导致死锁 。
等待-通知模式实现:lock 的 "等待-通知模式" 是通过 Condition 类实现的 , 调用 lock 对象的 newCondition() 方法去创建与之对应的 Condition 对象 , 然后调用 Condition 对象的 await 方法实现阻塞并释放资源给其他线程 , 等到其他线程执行完再调用 Condition 的 signal() 方法(对应Object中的 notify()方法)去随机唤醒一个阻塞的线程 , 而 signalAll()(对应notifyAll())则是唤醒 lock 对象对应的所有阻塞线程 。
下面就用一个例子来实现 。
1 public class lock2{ 23static lock2 ll=new lock2(); 4ReentrantLock lock=new ReentrantLock(); 5Condition cc=lock.newCondition(); 67public static void main(String[] args) { 8new Thread(new qq()).start(); 9new Thread(new qq2()).start();10}11public static class qq implements Runnable{12 13@Override14public void run() {15ll.aa();16}1718}19public static class qq2 implements Runnable{2021@Override22public void run() {23ll.bb();24}2526}2728public void aa() {29lock.lock();30try {31System.out.println("aa方法开始了"+Thread.currentThread().getName());32Thread.sleep(2000);33cc.await();34System.out.println("aa方法结束了"+Thread.currentThread().getName());35} catch (InterruptedException e) {36e.printStackTrace();37}finally {38lock.unlock();39}40}41public void bb() {42lock.lock();43try {44System.out.println("bb方法开始了"+Thread.currentThread().getName());45Thread.sleep(2000);46System.out.println("bb方法结束了"+Thread.currentThread().getName());47cc.signal();48} catch (InterruptedException e) {49e.printStackTrace();50}finally {51lock.unlock();52}53}5455 }结果:
Lock、Synchronized锁区别解析文章插图