博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lock锁---实现安全卖票
阅读量:3952 次
发布时间:2019-05-24

本文共 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:

  1. 优势:

       此种方式最大的好处就是不需要显式的去加锁释放锁,线程A执行到同步代码块的地方,自动判断synchronized是否有对象锁,有则进入同步代码块中执行任务,没有对象锁就说明此刻有其他线程B正在执行此同步代码块,线程A则进入阻塞状态。

  2. 劣势:

      相比较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/

你可能感兴趣的文章
Implementing Adaptative UI Flows 实施自适应用户界面流程
查看>>
Crossfading Two Views 淡入淡出的两种观点
查看>>
Using ViewPager for Screen Slides 使用屏幕幻灯片ViewPager
查看>>
Displaying Card Flip Animations 显示卡片翻转动画
查看>>
Zooming a View 缩放视图
查看>>
Animating Layout Changes 动画布局的更改
查看>>
Controlling Your App’s Volume and Playback 控制应用程序的音量和播放
查看>>
Managing Audio Focus 管理音频焦点
查看>>
Dealing with Audio Output Hardware 处理音频输出硬件设备
查看>>
Monitoring the Battery Level and Charging State 监测电池电量和充电状态
查看>>
Determining and Monitoring the Docking State and Type 判断并监测设备的停驻状态与类型
查看>>
Determining and Monitoring the Connectivity Status 根据网络连接状况去省电
查看>>
Manipulating Broadcast Receivers On Demand 按需操控广播接收
查看>>
Creating a View Class 创建一个视图类
查看>>
Custom Drawing 自定义绘制
查看>>
Making the View Interactive 视图互动
查看>>
Optimizing the View 优化视图
查看>>
Setting Up the Search Interface 设置搜索界面
查看>>
Storing and Searching for Data 数据存储和搜索
查看>>
Remaining Backward Compatible 保持向后兼容
查看>>