显示锁ReentrantLock和Condition的使用
一、ReentrantLock
(1)、java.util.concurrent.locks包中的ReentrantLock就是重入锁,它实现了Lock接口,Lock加锁和解锁都是显示的。ReentrantLock重入锁可以实现synchronized关键字的功能。
主要方法:
lock:获得锁。
unlock:释放锁。
(2)、java对synchronized优化之后,ReentrantLock和synchronize大的区别:
a、锁的粒度,ReentrantLock更细,更灵活。
b、ReentrantLock可以指定锁的公平性。synchronize只能是非公平的。
c、ReentrantLock可以利用Condition(条件)类选择性分组唤醒线程。
d、ReentrantLock可以中断一个正在等待获取锁的线程。lockInterruptibly()。
(3)、典型的使用格式:
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
测试i++的代码:
注意:必须在finally块中调用unlock语句释放锁,以确保即使在方法体中抛出异常(try块)锁也会释放锁。否则这个锁永远不释放。
/** * @author monkjavaer * @date 2018/12/16 22:24 */ public class ReentrantLockService{ private Lock lock = new ReentrantLock(); private int count = 0; public void getCount(){ try { //获得锁 lock.lock(); System.out.println("thread :"+Thread.currentThread().getName()+" count = "+count++); } catch (Exception e) { e.printStackTrace(); }finally { //在finally块中调用unlock语句,以确保即使在方法体中抛出异常(try块)也会释放锁。 lock.unlock(); } } public static void main(String[] args) { ReentrantLockService service = new ReentrantLockService(); for(int i=0; i<100; i++){ new Thread("" + i){ @Override public void run(){ service.getCount(); } }.start(); } } }
二、Condition
(1)、Condition通过Lock对象调用newCondition()方法获得。借助Lock,Condition可以实现wait && notify同样的功能。主要方法:
await(): 使当前线程等待
signal():唤醒一个等待的线程
signalAll():唤醒所有等待的线程
(2)、在使用Condition的方法时需要先获得锁,即调用Lock对象的lock()方法,否则会抛出IllegalMonitorStateException,因为没有监视器对象。
Condition使用实例:
/** * @author monkjavaer * @date 2018/12/18 21:14 */ public class ConditionService { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void awaitTest(){ try { lock.lock(); System.out.println("before await()"); condition.await(); System.out.println("after await()"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void signalTest(){ try { lock.lock(); System.out.println("before signal()"); condition.signal(); System.out.println("after signal()"); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public static void main(String[] args) { ConditionService service = new ConditionService(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { service.awaitTest(); } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run() { service.signalTest(); } }); thread2.start(); } }