java多线程【线程安全问题】
(一)问题描述
我们 先通过代码案例看线程执行过程中会发生那些安全问题
模拟电影院卖票:
某电影院目前正在上映国产大片,共有100张票,而它有3个平台卖票,请设计一个程序模拟该电影院卖票。
分析:事:卖票
卖:窗口 【不同的窗口卖相同的票】
程序中窗口就是线程对象【Thread的对象】,卖票是线程任务【Runnable的对象】
具体代码实现:
package com.tlc.thread;public class SellTicket implements Runnable {//定义初始票数int ticket = 100;@Overridepublic void run() {while(ticket > 0) {try {//线程睡眠就代表正在出票Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口:" + Thread.currentThread().getName() + "买票成功!"+ "还剩" + --ticket + "张票");}}
}public class SellTicketTest {public static void main(String[] args) {//创建线程任务SellTicket ticket = new SellTicket();//创建三个线程对象模拟三个窗口Thread thread1 = new Thread(ticket, "窗口一");Thread thread2 = new Thread(ticket, "窗口二");Thread thread3 = new Thread(ticket, "窗口三");//启动线程,三个窗口开始卖票thread1.start();thread2.start();thread3.start();}
}
结果:
(二)案例中出现的问题
从上代码执行的结果中我们发现一张票被不同的窗口买了多次,这就是线程安全问题
产生的原因:
多条线程同时操作同一个资源造成的混乱的执行结果
(三)解决
目的:就是同步线程
解决方案:
1.同步代码块
2.同步方法
3.Lock接口
1)同步代码块
1. 格式: synchronized(锁对象) { 发生线程安全的代码 }
2.锁对象:可以是任意的引用数据类型的对象,但是一旦确定就要保证其唯一性
3.优缺点
优点:解决了多线程的数据安全问题;
缺点:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
代码实例【只是对run方法进行改进,其他代码不变】:
@Overridepublic void run() {//开始卖票while (ticket > 0) {//这里加锁,只有拿到锁对象的线程才可以进去执行synchronized ("a") {//由于买到最后一张票时,三个线程都会进来,这样就会造成票为负数的现象,//因此在这里要进行判断票数if (ticket > 0) {try {//线程睡眠就代表正在出票Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口:" + Thread.currentThread().getName() + "买票成功!"+ "还剩" + --ticket + "张票");}}}}
2)同步方法
1.格式:
修饰符 (static) synchronized 返回值类型 方法名(方法参数){方法体}
锁对象: 成员同步方法锁对象是,this;而静态同步方法锁对象是,类名. class 。
主要代码:
@Overridepublic void run() {//开始卖票while (ticket > 0) {sellTicket();}}public static synchronized void sellTicket() {if (ticket > 0) {try {//线程睡眠就代表正在出票Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口:" + Thread.currentThread().getName() + "买票成功!"+ "还剩" + --ticket + "张票");}}
3)Lock锁
1.为了更清晰的表达如何加锁和释放锁
- JDK5以后提供了一个新的锁对象Lock,Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化。
2.方法介绍
ReentrantLock构造方法: ReentrantLock( )
加锁解锁方法: lock( ):获得锁
unlock( ):释放锁
具体实现代码:
//定义初始票数/*static*/ int ticket = 100;//创建Lock对象ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {//开始卖票while (ticket > 0) {//获得锁lock.lock();if (ticket > 0) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("窗口:" + Thread.currentThread().getName() + "买票成功!"+ "还剩" + --ticket + "张票");}//释放锁lock.unlock();}}
以上部分如有错误之处,欢迎各位大佬留言解释,谢谢!
版权声明:本文为CSDN博主「喵了个@汪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44919512/article/details/119487021
如果看完对你的学习有帮助,感谢点赞支持!
java多线程【线程安全问题】相关推荐
- Java多线程——线程安全问题
一.什么情况下会产生线程安全问题? 同时满足以下两个条件时: 1,多个线程在操作共享的数据. 2,操作共享数据的线程代码有多条. 当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会 ...
- Java多线程 - 线程安全问题
文章目录 1. 什么是线程安全和线程不安全? 2. 自增运算为什么不是线程安全的? 3. 临界区资源和竞态条件 面试题: 什么是线程安全和线程不安全? 自增运算是不是线程安全的?如何保证多线程下 i+ ...
- Java——多线程(线程安全问题)
同步为安全,不同步为不安全:也就是有synchronized这个标识符,就为线程安全,反之,为线程不安全. ①Vector是线程安全的 ②StringBuffer是线程安全的 ③Hashtable是线 ...
- Java 多线程线程安全(面试概念解答二)
Java 多线程线程安全 什么是线程安全? 为什么有线程安全问题? 线程安全解决办法? 同步代码块 同步函数 静态同步函数 多线程死锁 多线程的三大特性 原子性 可见性 有序性 Java内存模型 Vo ...
- JAVA --- 多线程 -- 线程的创建
JAVA - 多线程 – 线程的创建 线程的概念: 说起线程,先说程序和进程,多任务的概念. 程序(program):是指令和数据的有序集合,本身没有任何运行的含义,是一个静态的概念. 进程(proc ...
- Java多线程——线程的优先级和生命周期
Java多线程--线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...
- java多线程 线程安全_Java中的线程安全
java多线程 线程安全 Thread Safety in Java is a very important topic. Java provides multi-threaded environme ...
- java多线程-线程的停止【interrupt】
java多线程-线程的停止 文章目录 java多线程-线程的停止 线程停止的原理 如何正确停止线程 在普通情况下停止线程 代码展示 在阻塞情况下停止线程 代码展示 线程在每次迭代后都阻塞 代码展示 停 ...
- servlet单实例多线程 ---线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。(所有建议不要在servlet中定义成员变
Servlet 单例多线程 Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servl ...
- Java多线程 ——线程基础和锁锁锁
Java多线程(一) 一.线程的定义 二.Synchronize线程同步 三.偏向锁.自旋锁.重量级锁 四.volatile关键字 4.1.普通变量运算的物理意义 4.2.有无解决的方案 4.3.vo ...
最新文章
- 4月23日遇到的问题
- web 点击劫持 X-Frame-Options
- 文巾解题 1310. 子数组异或查询
- 20 条非常实用的 Python 代码,建议收藏!
- PHP微信支付没有收到微信的回调怎么修改订单状态:主动查询
- 深度学习笔记——基于传统机器学习算法(LR、SVM、GBDT、RandomForest)的句子对匹配方法
- Django中session和cookie简单的使用
- 将经过身份验证的用户注入Spring MVC @Controllers
- 基于matlab的信号与系统实例,华南理工大学信号与系统实验基于Matlab的信号处理实例...
- python之字典的操作
- CSS详解(一)——CSS基本原理
- pmp学习资料下载-pmp备考
- LM小型可编程控制器软件(基于CoDeSys)笔记二十七:温度电阻通道和DO通道
- Linux树莓派实战案例论文,树莓派|树莓派使用实例之:2 Pi R
- TryHackMe-Misguided Ghosts(boot2root)
- 【深度学习】Github 最受欢迎的深度学习项目 TOP 20
- web应用F12查看报错(前后端bug判断、2XX/3XX/4XX/5XX常见状态码解析)
- PDF→Excel格式转换工具集锦
- 技术分享1: jinkens构建Android工程,并上传到蒲公英平台
- gateway的官方文档解读
热门文章
- C语言 指针+二维数组详解 (应付期末、考研的最强笔记,建议收藏)
- 并查集——家谱(洛谷 P2814)
- 深层神经网络——线性模型的局限性
- 计算机科学与技术专业热,广东省计算机科学与技术专业最“热”
- mysql讀取sql_MySQL数据库之python json及mysql读取json文件存sql等问题
- 那些年删过的库,跑过的路,你从中找到解决方法了吗?
- 分盘存储:实现数据库备集群备份文件分散存储
- Volcano 监控设计解读,一看就懂
- 懂分析、会预测,你见过这样的华为云DAS吗?
- 昇腾AI处理器软件栈--运行管理器(Runtime)