本文共 2251 字,大约阅读时间需要 7 分钟。
上一篇文章中:,我们使用了synchronized
同步代码块来实现了线程安全,这篇文章我们使用Lock
锁来实现同样的效果。
Lock锁介绍 |
Lock
锁是java jdk1.5版本之后添加一个处理线程安全问题的接口。相比较synchronized
而言,更加灵活,因为它不在局限于一个代码块,实现了一些synchronized
同步锁所不能实现的功能。
卖票案例代码实现 |
public class RunnableImpl implements Runnable { //给一个共享资源 private int ticket = 100; //new 一个Lock锁的实现类对象 Lock lock = new ReentrantLock(); //指定线程所要执行的任务(卖票) @Override public void run() { while (true) { //在可能会出现线程安全问题的地方 显式的调用lock中的.lock()方法进行加锁 lock.lock(); if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张电影票"); //为了卖票出错的情况更加明显,我们让线程等待100ms try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } --ticket; } //在代码执行结束的地方,显式的调用lock对象中的.unlock()方法,释放锁资源 lock.unlock(); } }}
public class FileTest { public static void main(String[] args) { //思考:为什么这里只new 了一个Runnable的对象传到了三个线程种? RunnableImpl runnable = new RunnableImpl(); //new 三个线程出来模三个窗口,为了符合情景,我们为线程设置一个线程名 Thread thread1 = new Thread(runnable); thread1.setName("窗口1"); Thread thread2 = new Thread(runnable); thread2.setName("窗口2"); Thread thread3 = new Thread(runnable); thread3.setName("窗口3"); thread1.start(); thread2.start(); thread3.start(); }}
启动项目之后,发现直接从100张电影票顺序卖出去了,说明使用Lock锁成功解决了线程安全问题。
synchronized和Lock比较 |
synchronized:
优势:
此种方式最大的好处就是不需要显式的去加锁
和释放锁
,线程A执行到同步代码块的地方,自动判断synchronized
是否有对象锁,有则进入同步代码块中执行任务,没有对象锁就说明此刻有其他线程B正在执行此同步代码块,线程A则进入阻塞状态。 劣势:
相比较Lock
而言,synchronized
同步锁比较死板,不够灵活,因为synchronized
一般使用在同步代码块或者同步方法上,都可以看作是一个块状结构,也就是强制要求了所有的获取锁和释放锁都必须在一个块结构中。但是Lock
就没有此种困扰。 Lock:
Lock
的优势不再赘述,这里就强调一点:使用Lock
一定要注意不要忘记添加lock.unlock()
显示的释放锁资源,在项目开发的过程中,我们一般将它放到try()catch{……}finnly{lock.unlock()}
的finnly{}代码块中,也就是说,无论try()代码块中有没有捕获到异常,该锁始终会被释放掉。 public class RunnableImpl implements Runnable { //给一个共享资源 private int ticket = 100; //new 一个Lock锁的实现类对象 Lock lock = new ReentrantLock(); //指定线程所要执行的任务(卖票) @Override public void run() { while (true) { lock.lock(); if (ticket > 0) { try { System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张电影票"); //为了卖票出错的情况更加明显,我们让线程等待100ms --ticket; } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } }}
转载地址:http://ojhwi.baihongyu.com/