Lock有别于synchronized隐式锁的三个特征:能够响应中断。支持超时和非阻塞地获取锁,也就是说lock比synchronized的功能丰富。
JavaSDK并发包通过Lock和Condition两个接 口来实现管程,其中Lock用于解决互斥问题,Condition用于解决同步问题 。
Lock接口的三个方法:
// ⽀持中断的API void lockInterruptibly() throws InterruptedException; // ⽀持超时的API boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // ⽀持⾮阻塞获取锁的API boolean tryLock();
class X { private final Lock rtl = new ReentrantLock(); int value; public void addOne() { // 获取锁 rtl.lock(); try { value+=1; } finally { // 保证锁能释放 rtl.unlock(); } } }
指线程可以重复获取同一把锁 。
//⽆参构造函数:默认⾮公平锁 public ReentrantLock() { sync = new NonfairSync(); } //根据公平策略参数创建锁 fair=true是公平锁 public ReentrantLock(boolean fair){ sync = fair ? new FairSync() : new NonfairSync(); }
线程可以重复获取同一把锁。
/** * 当线程t执行到①处时,已经获取到了锁rtl, * 当在①处调用get()方法时,会在②再次对锁rtl执行加锁操作。 * 此时,如果锁 rtl 是可重入的,那么线程T1可以再次加锁成功;如果锁 rtl 是不可重入` * 的,那么线程t此时会被阻塞。 */ public class ReentrantLockExample { private final Lock rtl = new ReentrantLock(); int value; public int get() { // 获取锁 rtl.lock(); //② try { return value; } finally { // 保证锁能释放 rtl.unlock(); } } public void addOne() { // 获取锁 rtl.lock(); try { value = 1 + get(); //① } finally { // 保证锁能释放 rtl.unlock(); } }
可重入函数: 多个线程可以同时调用该函数。
可重入函数是线程安全的。
ReentrantLock这个类有两个构造函数,一个是无参构造函数,一个是传入fair参数的构造函数。fair参数代表的是锁的公平策略,如果传入true就表示需要构造一个公平锁,反 之则表示要构造一个非公平锁。
//创建ReentrantLock时传入true是公平锁 private final Lock rtl = new ReentrantLock(true); //false或者不传值是非公平锁 private final Lock rtl = new ReentrantLock();
如何实现程序支持异步: