ReentrantLock重入锁

ReentrantLock重入锁

  • 简述
  • 特性
  • Condition条件

简述

重入锁ReentrantLock可以完全替代synchronized关键字。而且重入锁可以灵活性更高,功能更强大。在JDK1.5之前性能也更好,但是从JDK1.6开始,JDK在synchronized中做了大量的优化,两者的性能差距并不会很大。

public class ReenterLock implements Runnable{
    public static ReentrantLock lock = new ReentrantLock();
    public static int i = 0;
    public void run(){
        forint j = 0;j<10000;j++){
            lock.lock();
            lock.lock(); //重入锁
            try{
                i++;
            }finally{
                lock.unlock();
                lock.unlock();
            }
        }
    }
}

特性

  1. 必须手动加锁,手动释放锁;
  2. 在一个线程内,同一个锁可以多次获取,当然在释放锁的时候也要多次释放。这也是名叫重入锁的原因。重入锁可以避免和自己产生死锁。
lock.lockInterruptibly();//可响应中断的加锁操作
thread.interrupt();//中断线程
  1. 响应中断:上述是一个可以对中断进行响应的锁申请动作,也就是在等待锁的过程中,可以响应中断。对于synchronized来说,如果一个线程在等待锁,那么只有两情况,要么获得锁继续执行,要么保持等待,无法做到响应中断。
if(lock.tryLock(5,TimeUnit.SECONDS)){
    System.out.println("get lock success");
}else{
    System.out.println("get lock failed");
}
  1. 锁申请等待限时:tryLock()方法也可以不带参数直接运行。锁未被占用,则申请锁会成功,并立即返回true,若锁被其他线程占用,当前线程不会进行等待,而是立即返回false。这种模式不会引起线程等待,因此也不会产生死锁。
  2. 公平锁:公平锁的一大特点是不会产生饥饿现象。即每一个线程最终还是可以等到资源的。而synchronized关键字进行锁控制的话,产生的锁就行不公平的。重入锁ReentrantLock允许对其公平性进行设置。对应的构造函数:
public ReentrantLokc(boolean fair)

但是实现公平锁必然要求系统维护一个有序队列,因此公平锁的实现成本比较高。默认情况下,锁是非公平的。

  1. lock():获得锁,如果锁已经被占用,则等待。
  2. lockInterruptibly():获得锁,但优先响应中断
  3. tryLock():尝试获得锁,该方法不等待,立即返回。
  4. tryLock(long time,TimeUnit unit):在给定时间内尝试获得锁
  5. unlock():释放锁
  6. ReentrantLock的实现主要集中在JDK层面,而synchronized是jvm层面。

Condition条件

  1. 通过Lock接口的Condition newCondition()方法可以生成一个与当前重入锁绑定的Condition实例。这个Condition对象可以让线程在合适的时间等待,或者在某一特定的时刻得到通知唤醒线程。作用与wait()和notify()方法大体一致。
  2. await()方法会使当前线程等待,同时释放当前锁资源。其他线程私用signal()或者signalAll()方法时,线程会重新获得锁并继续执行。当线程被中断时,也能跳出等待。
  3. awaitUninterruptibly()方法与await()方法基本相同,但它不会在等待过程中响应中断。
  4. signal()方法用于唤醒一个在等待中的线程。signalAll()唤醒所有在等待中的线程。唤醒线程的前提时,要求线程先获得相关的锁。唤醒后一般需要释放相关的锁,谦让资源给被唤醒的线程。

你可能感兴趣的:(java并发)