重入锁ReentrantLock
重入锁能代替关键字synchronized进行使用,在jdk1.6以后,synchronized与重入锁的性能差距并不大。它与关键字synchronized相比,重入锁有着显示的操作过程,我们必须手动指定何时加锁,何时释放锁。也是因为这样,重入锁对逻辑控制的灵活性就远远优于关键字synchronized,但我们需要注意在退出临界区时,必须记得释放锁,否则其他线程就没有机会再访问临界区了。
简单使用代码:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockTest implements Runnable{
public static ReentrantLock lock=new ReentrantLock();
public static int i=0;
@Override
public void run(){
for (int j=0;j<1000000;j++){
lock.lock();
try{
i++;
}finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
ReentrantLockTest t=new ReentrantLockTest();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
运行结果:
为什么该锁叫做重入锁呢?是因为这种锁是可以反复进入的,一个线程可以连续多次获得同一把锁。但我们也需要注意,如果同一个线程多次获得锁,那么在释放锁的时候,也必须释放相同次数。
- 释放次数多了,就会得到一个ILLegalMonitorStateException异常;
- 释放次数少了,那么就相当于线程还持有这个锁,会占用资源,其他线程也无法进入临界区。
ReentrantLock几个重要方法如下:
- lock():获得锁,如果锁已经被占用,则等待;
- lockInterruptibly():获得锁,但优先响应中断;
- tryLock():尝试获得锁,如果成功,则返回true,失败返回false。该方法不等待,立即返回;
- tryLock(Long time,TimeUnit unit):在给定的时间内获得锁;
- unlock():释放锁。