一、锁接口 Lock,ReadWriteLock:
1、Lock,实现类有ReentractLock、WriteLock、ReadLock;
2、ReadWriteLock,主要实现类是ReentrantReadWriteLock,有两个方法 writeLock()、readLock() ,返回值是 WriteLock,ReadLock,这两类继承与Lock接口;
3、常用方法:
lock() / unlock():获取/释放锁,lock()会阻塞直到成功
lockInterruptibly():与lock() 不同的是它可以响应中断,如果被其他线程中断了,则抛出InterruptedException
tryLock() / tyrLock(long time, TimeUnit unit):只是尝试获取锁,立即返回,返回值为 boolean。无参数不阻塞,有参数会根据设置的时间阻塞等待,如果发生中断抛出InterruptedException
newCondition:新建一个条件,一个lock可以关联多个条件
二、对比 ReentractLock 和 synchornized:
相比synchronized,ReentractLock可以实现与synchronized 相同的语义,而且支持以非阻塞方法获取锁,可以响应中断,可以限时,更为灵活。不过,synchronized 的使用更为简单,写的代码更少,也不容易出错。
三、Condition:
锁用于解决竞态条件问题,条件是线程间的协作机制。显示锁与synchronized 相对应,而显式条件与wait/notify 相对应。wait/notify 与synchronized 配合使用,显式条件与显示锁配合使用。
1、声明:Condition c = reentractLock.newCondition();
2、常用方法:
await() / signal():等待/通知,使用时需获取锁,await() 发生中断,抛出 InterruptedException,但中断标志位会被清空。awaitUniterruptibly() 不响应中断
四、ReentractLock、Condition 搭配使用:
/** * ReentrantLock 显式锁 * * Condition 显式条件 * * 生产者、消费者协作模式 */ public class ReentrantLockTest { private int e = 1; private int num = 30; //private BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(num); private Queue<Integer> queue = new ArrayDeque<>(num); private Lock lock = new ReentrantLock(); private Condition queueFull = lock.newCondition(); private Condition queueEmpty = lock.newCondition(); public static void main(String[] args) throws InterruptedException { ReentrantLockTest reentrantLockTest = new ReentrantLockTest(); for(int i = 0; i < reentrantLockTest.num; i++){ new Thread(() -> { try { reentrantLockTest.producer(); Thread.sleep((int)(Math.random() * 100)); } catch (InterruptedException e1) { e1.printStackTrace(); } }).start(); } for(int i = 0; i < reentrantLockTest.num; i++){ new Thread(() -> { try { reentrantLockTest.consumer(); Thread.sleep((int)(Math.random() * 100)); } catch (InterruptedException e1) { e1.printStackTrace(); } }).start(); } } public void producer() throws InterruptedException { lock.lockInterruptibly(); try{ while (queue.size() == num){ queueFull.await(); } queue.add(e++); System.out.println("producer" + Arrays.toString(queue.toArray())); queueEmpty.signal(); }finally { lock.unlock(); } } public void consumer() throws InterruptedException { lock.lockInterruptibly(); try{ while (queue.isEmpty()){ queueEmpty.await(); } System.out.println("poll:" + queue.poll() + ",comsumer" + Arrays.toString(queue.toArray())); queueFull.signal(); }finally { lock.unlock(); } } }