2019独角兽企业重金招聘Python工程师标准>>>
我们首先将介绍synchronized、Object.wait()和Object.notify()方法的替代品(或者说是增强版) ——重入锁。
一、synchronized的功能扩展:重入锁
重入锁可以完全替代synchronized关键字。在JDK5.0的早期版本中,重入锁的性能远远好于synchronized,但从JDK6.0开始,JDK在synchronized上做了大量的优化,是的两者的性能差距并不大。重入锁使用java.util.concurrent.locks.ReentrantLock类来实现。下面是一段最简单的重入锁使用案例:
import java.util.concurrent.locks.ReentrantLock;public class Thread2 implements Runnable{public static ReentrantLock lock &#61; new ReentrantLock();public static int i&#61;0;&#64;Overridepublic void run() {for (int j &#61; 0; j <1000000; j&#43;&#43;) {lock.lock();try {i&#43;&#43;;}finally {lock.unlock();}}}public static void main(String[] args) throws InterruptedException {Thread2 rl &#61; new Thread2();//类名Thread t1 &#61; new Thread(rl);Thread t2 &#61; new Thread(rl);t1.start();t2.start();//启动子线程t1、t2t1.join();t2.join();//结束子线程t1、t2System.out.println(i);}
}
根据以上代码&#xff0c;使用重入锁保护临界区资源i&#xff0c;确保多线程对i操作的安全性。从这段代码可以看到&#xff0c;与synchronized相比&#xff0c;重入锁有着显示的操作过程。开发人员必须手动何时枷锁&#xff0c;何时释放锁。也正因为这样&#xff0c;重入锁对逻辑控制的灵活性要远远好于synchronized&#xff0c;但值得注意的是&#xff0c;在退出临界区时&#xff0c;必须记得释放&#xff0c;否则&#xff0c;其它线程就没有机会再访问临界区了。
for (int j &#61; 0; j <1000000; j&#43;&#43;) {lock.lock();lock.lock();try {i&#43;&#43;;}finally {lock.unlock();lock.unlock();}
}
一个线程连续两次获得同一把锁。这是允许的&#xff01;如果不允许这么操作&#xff0c;那么同一个线程在第2次获得锁时&#xff0c;将会和自己产生死锁。程序就会“卡死”在第2次申请锁的过程中。需要注意的是&#xff0c;如果同一个线程多次获得锁&#xff0c;那么在释放锁的时候&#xff0c;也必须释放相同次数。
- 释放锁的次数多了&#xff1a;会得到一个java.lang.IllegalMonitorStateException异常。
- 释放锁的次数少了&#xff1a;相当于线程还持有这个锁&#xff0c;因此其它线程也无法进入临界区。