重入锁是对synchronize的增强,可以代替synchronize。
重入锁使用java.util.concurrent.locks.ReentrantLock来实现。下面是一个简单的例子,相对于synchronize来说,重入锁更加细致,也更加灵活。
public class threadDemo implements Runnable{ public static ReentrantLock lock=new ReentrantLock() ; public static int i=0; public static void main(String[] args) throws InterruptedException { threadDemo t=new threadDemo(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start();t1.join(); t2.start();t2.join(); System.out.println(i); } public void run() { for(int j=0;j<10000;j++) { lock.lock(); try { i++; } finally { lock.unlock(); } } } }
之所以叫重入锁,是因为对同一线程来说,这种锁是可以反复进入的。
它还可以获得数次锁,如下所示
for(int j=0;j<10000;j++) { lock.lock(); lock.lock(); try { i++; } finally { lock.unlock(); lock.unlock(); } }
但一定要记得获得多少锁也要释放多少锁。
另外,重入锁是可以被中断的,比如设置两个锁AB,线程一先获得A再获得B,线程二先获得B再获得A,此时容易死锁,可以通过中断的方式退出
lock.lockInterruptibly();
为了避免死锁问题,重入锁还提供了一个限时等待的方法
lock.tryLock(timeout, unit)
为了避免饥饿问题,重入锁还可以设置公平锁,在构造的时候。
public static ReentrantLock lock=new ReentrantLock(true) ;
下面的一张图是对重入锁这些方法的总结
condition之于重入锁,相当于wait,notify之于synchronize。用法也差不多。
condition可以通过lock来实例化,两个await() signal()方法和synchronize的两个对应
public static ReentrantLock lock=new ReentrantLock(true) ; public static Condition condition=lock.newCondition(); condition.await(); condition.signal();