Java并发--同步锁Lock 柔情只为你懂 2021-08-14 01:38 488阅读 0赞 ### Lock接口 ### 在Java1.5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要**显示地获取和释放锁**。虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。 Lock的使用非常简单。如下所示: Lock lock = new ReentrantLock(); lock.lock(); try{ }finally{ lock.unlock(); } 在finally块中释放锁,目的是保证在获取到锁之后,最终能够被释放。 不要将获取锁的过程写在try块中,因为如果在获取锁(自定义的实现)时发生了异常,异常抛出的同时,**也会导致锁无故释放!** Lock接口提供的synchronized关键字所具备的主要特性如下: <table> <thead> <tr> <th align="left">特性</th> <th align="left">描述</th> </tr> </thead> <tbody> <tr> <td align="left">尝试非阻塞地获取锁</td> <td align="left">当前线程尝试获取锁,如果这一时刻没有被其他线程获取到,则成功获取并持有锁</td> </tr> <tr> <td align="left">能被中断地获取锁</td> <td align="left">与synchronized不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁会释放</td> </tr> <tr> <td align="left">超时获取锁</td> <td align="left">在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获取锁,则返回</td> </tr> </tbody> </table> Lock接口的API: <table> <thead> <tr> <th align="left">方法</th> <th align="left">描述</th> </tr> </thead> <tbody> <tr> <td align="left"><strong>void lock()</strong></td> <td align="left">获取锁,调用该方法当前线程将会获取锁,当锁获取后,从该方法返回</td> </tr> <tr> <td align="left"><strong>void lockInterruptibly() throws InterruptedException</strong></td> <td align="left">可中断地获取锁,和lock方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程</td> </tr> <tr> <td align="left"><strong>boolean tryLock()</strong></td> <td align="left">尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回true,否则返回false</td> </tr> <tr> <td align="left"><strong>boolean tryLock(long time, TimeUnit unit) throws InterruptedException</strong></td> <td align="left">超时的获取锁,当前线程在以下3种情况下会返回:<br>1. 当前线程在超时时间内获得了锁<br>2. 当前线程在超时时间内被中断<br>3. 超时时间结束,返回false</td> </tr> <tr> <td align="left"><strong>void unlock()</strong></td> <td align="left">释放锁</td> </tr> <tr> <td align="left"><strong>Condition new Condition()</strong></td> <td align="left">获取等待通知组件,该组件和当前线程的锁绑定,当前线程只有获得了锁,才能调用该组件的wait()方法,而调用后,当前线程将释放锁</td> </tr> </tbody> </table> ### 模拟一个简单的抢票案例 ### package pers.zhang.juc.part1; import sun.security.krb5.internal.Ticket; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author zhang * @date 2020/1/17 - 19:54 */ public class TestLock { public static void main(String[] args) { TrainTicket ticket = new TrainTicket(); new Thread(ticket, "1号窗口").start(); new Thread(ticket, "2号窗口").start(); new Thread(ticket, "3号窗口").start(); } } class TrainTicket implements Runnable{ private int tick = 100; private Lock lock = new ReentrantLock();//Lock的实现类 @Override public void run() { while(true){ lock.lock(); //上锁 try{ if(tick > 0){ try { Thread.sleep(200); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick); } }finally{ lock.unlock(); //释放锁 } } } }
还没有评论,来说两句吧...