重入锁采用ReentrantLock 实现,和同步关键字sychronized都可以用来在多线程环境下保护临界区资源,确保安全性。重入锁相比sychronized有着显示的操作过程,需要手动控制何时加锁和解锁(如不解锁则会造成死锁),之所以称为重入锁,是因为锁是可以反复进入的,即同一个线程可以连续多次获得锁而不会造成死锁,相应的解锁也需要多次,否则会造成其它线程因为获取不到锁而无法访问临界区资源。
重入锁可以替换sychronized,instance是类的实例,请自行添加ReenterLock instance = new ReenterLock();例如:
public class ReenterLock implements Runnable{
private static ReentrantLock lock = new ReentrantLock();
private static int i = 0;
@Override
public void run() {
for (int j = 0; j < 100000; j++) {
//加锁保证对变量i的安全访问
lock.lock();
try {
i++;
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException{
//注意两个线程要指向的是同一实例(关注的是同一个对象锁)
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
用同步关键字也是保证对变量 i 访问的安全性的,例如:
public class ReenterLock implements Runnable{
private static ReenterLock instance = new ReenterLock();
private static int i = 0;
public static synchronized void increase() {
i++;
}
//两种同步方式都可行,任选一种
@Override
public void run() {
for (int j = 0; j < 100000; j++) {
synchronized (instance) {
i++;
}
}
}
/*@Override
public void run() {
for (int j = 0; j < 100000; j++) {
increase();
}
}*/
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
使用重入锁和同步关键字输出结果均是一致的。
关于重入锁的高级应用,如中断响应、限时等待锁、condition条件,有兴趣的可以自行了解。推荐书籍:实战java高并发程序设计