java多线程之Lock锁原理以及案例实现电影院卖票

2023-10-06 15:50

本文主要是介绍java多线程之Lock锁原理以及案例实现电影院卖票,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

为什么会出现Lock锁?

我们知道 synchronized 给代码加锁或解锁时,我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

Lock锁使用

Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
Lock中提供了获得锁和释放锁的方法:

  • void lock();//获得锁
  • void unlock();//释放锁
  • Lock类是接口,不能直接实例化,这里采用他的实现类ReentrantLock来实例化
    ReentrantLock的构造方法
    ReentrantLock():创建一个ReentrantLock的实例

代码实战

需求:某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票

package com.heima.thread001;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class MyRun implements Runnable {int ticket = 0;Lock lock = new ReentrantLock();@Overridepublic void run() {while (true){lock.lock();try {if (ticket == 100) {break;}else {ticket ++;System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票 ...");}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}
}
package com.heima.thread001;import java.util.concurrent.ExecutionException;public class TestDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {MyRun myRun = new MyRun();//创建线程对象Thread t1 = new Thread(myRun);Thread t2 = new Thread(myRun);Thread t3 = new Thread(myRun);//起名字t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");//开启线程t1.start();t2.start();t3.start();}
}

运行结果如下:

窗口1正在卖第1张票 ...
窗口3正在卖第2张票 ...
窗口3正在卖第3张票 ...
窗口3正在卖第4张票 ...
窗口3正在卖第5张票 ...
窗口3正在卖第6张票 ...
窗口3正在卖第7张票 ...
窗口3正在卖第8张票 ...
窗口3正在卖第9张票 ...
窗口3正在卖第10张票 ...
窗口3正在卖第11张票 ...
窗口3正在卖第12张票 ...
窗口3正在卖第13张票 ...
窗口3正在卖第14张票 ...
窗口3正在卖第15张票 ...
窗口3正在卖第16张票 ...
窗口3正在卖第17张票 ...
窗口3正在卖第18张票 ...
窗口3正在卖第19张票 ...
窗口3正在卖第20张票 ...
窗口3正在卖第21张票 ...
窗口3正在卖第22张票 ...
窗口3正在卖第23张票 ...
窗口3正在卖第24张票 ...
窗口3正在卖第25张票 ...
窗口3正在卖第26张票 ...
窗口3正在卖第27张票 ...
窗口3正在卖第28张票 ...
窗口3正在卖第29张票 ...
窗口3正在卖第30张票 ...
窗口3正在卖第31张票 ...
窗口3正在卖第32张票 ...
窗口3正在卖第33张票 ...
窗口3正在卖第34张票 ...
窗口3正在卖第35张票 ...
窗口3正在卖第36张票 ...
窗口3正在卖第37张票 ...
窗口3正在卖第38张票 ...
窗口3正在卖第39张票 ...
窗口3正在卖第40张票 ...
窗口3正在卖第41张票 ...
窗口3正在卖第42张票 ...
窗口3正在卖第43张票 ...
窗口3正在卖第44张票 ...
窗口3正在卖第45张票 ...
窗口3正在卖第46张票 ...
窗口3正在卖第47张票 ...
窗口3正在卖第48张票 ...
窗口3正在卖第49张票 ...
窗口3正在卖第50张票 ...
窗口3正在卖第51张票 ...
窗口3正在卖第52张票 ...
窗口3正在卖第53张票 ...
窗口3正在卖第54张票 ...
窗口3正在卖第55张票 ...
窗口3正在卖第56张票 ...
窗口3正在卖第57张票 ...
窗口3正在卖第58张票 ...
窗口3正在卖第59张票 ...
窗口3正在卖第60张票 ...
窗口3正在卖第61张票 ...
窗口3正在卖第62张票 ...
窗口3正在卖第63张票 ...
窗口3正在卖第64张票 ...
窗口3正在卖第65张票 ...
窗口3正在卖第66张票 ...
窗口3正在卖第67张票 ...
窗口3正在卖第68张票 ...
窗口3正在卖第69张票 ...
窗口3正在卖第70张票 ...
窗口3正在卖第71张票 ...
窗口3正在卖第72张票 ...
窗口3正在卖第73张票 ...
窗口3正在卖第74张票 ...
窗口3正在卖第75张票 ...
窗口3正在卖第76张票 ...
窗口3正在卖第77张票 ...
窗口3正在卖第78张票 ...
窗口3正在卖第79张票 ...
窗口3正在卖第80张票 ...
窗口3正在卖第81张票 ...
窗口3正在卖第82张票 ...
窗口3正在卖第83张票 ...
窗口3正在卖第84张票 ...
窗口3正在卖第85张票 ...
窗口3正在卖第86张票 ...
窗口3正在卖第87张票 ...
窗口3正在卖第88张票 ...
窗口3正在卖第89张票 ...
窗口3正在卖第90张票 ...
窗口3正在卖第91张票 ...
窗口3正在卖第92张票 ...
窗口3正在卖第93张票 ...
窗口3正在卖第94张票 ...
窗口3正在卖第95张票 ...
窗口3正在卖第96张票 ...
窗口3正在卖第97张票 ...
窗口3正在卖第98张票 ...
窗口3正在卖第99张票 ...
窗口3正在卖第100张票 ...

知识扩展

1、synchronized和Lock的区别?

  • synchronized是关键字,Lock是接口。
  • synchronized无法获取锁的状态,Lock可以。
  • synchronized会自动释放锁,Lock需要手动。
  • synchronized没有Lock锁灵活(Lock锁可以自己定制)。

2、ReentrantLock 和 Synchronized 对比

  • ReentrantLock 通过 lock() 和 unlock() 加解锁,Synchronized会自动解锁,ReentrantLock需要手动解锁
  • ReentrantLock相比Synchronized的优势是: 可中断,公平锁,多个锁

3、Lock 接口的主要方法

  • void lock() — 如果lock是空闲的,当前线程就会获取到锁
  • boolean tryLock() — 如果lock可用,则获取锁并且返回true,否则返回false
  • void unlock() — 当前线程释放持有的锁
  • Condition newCondition() — 条件对象: 获取等待通知组件
  • getHoldCount() — 查询当前线程保持此锁的次数
  • getQueueLength() — 返回正在等待此锁的线程数量
  • getWaitQueueLength() — 返回正在等待与此锁相关给定条件的线程数量
  • hasWaiters(Condition condition) — 查询在特定Condition下是否有线程等待
  • hasQueuedThread(Thread thread) — 查询给定线程是否等待获取此锁
  • hasQueuedThreads — 是否有线程等待此锁
  • isFair() — 该锁是否是公平锁
  • isHeldByCurrentThread() — 当前线程是否保持锁定
  • isLock() — 此锁是否有任意线程占用
  • lockInterruptibly() — 如果当前线程未被中断,获取锁
  • tryLock() — 尝试获取锁,仅在调用时锁未被线程占用,获得锁
  • tryLock(long timeout, TimeUnit unit) — 如果锁在给定等待时间没有被另一个线程保持,获取锁

锁优化

  • 减少锁持有的时间 — 只在有线程安全要求的程序上加锁
  • 减少锁粒度 — 将大的对象拆成小对象,增加并行度,减少锁竞争
  • 锁分离 — 读写锁的思想,读的时候加read lock, 写的时候加 write lock
  • 锁粗化 — 保证线程持有锁的时间尽量短
  • 锁消除 — 如果发现不能被共享的对象,需要消除这些对象的锁操作

这篇关于java多线程之Lock锁原理以及案例实现电影院卖票的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/153429

相关文章

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依