(一)问题描述

        我们 先通过代码案例看线程执行过程中会发生那些安全问题

模拟电影院卖票:

某电影院目前正在上映国产大片,共有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多线程【线程安全问题】相关推荐

  1. Java多线程——线程安全问题

    一.什么情况下会产生线程安全问题? 同时满足以下两个条件时: 1,多个线程在操作共享的数据. 2,操作共享数据的线程代码有多条. 当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会 ...

  2. Java多线程 - 线程安全问题

    文章目录 1. 什么是线程安全和线程不安全? 2. 自增运算为什么不是线程安全的? 3. 临界区资源和竞态条件 面试题: 什么是线程安全和线程不安全? 自增运算是不是线程安全的?如何保证多线程下 i+ ...

  3. Java——多线程(线程安全问题)

    同步为安全,不同步为不安全:也就是有synchronized这个标识符,就为线程安全,反之,为线程不安全. ①Vector是线程安全的 ②StringBuffer是线程安全的 ③Hashtable是线 ...

  4. Java 多线程线程安全(面试概念解答二)

    Java 多线程线程安全 什么是线程安全? 为什么有线程安全问题? 线程安全解决办法? 同步代码块 同步函数 静态同步函数 多线程死锁 多线程的三大特性 原子性 可见性 有序性 Java内存模型 Vo ...

  5. JAVA --- 多线程 -- 线程的创建

    JAVA - 多线程 – 线程的创建 线程的概念: 说起线程,先说程序和进程,多任务的概念. 程序(program):是指令和数据的有序集合,本身没有任何运行的含义,是一个静态的概念. 进程(proc ...

  6. Java多线程——线程的优先级和生命周期

    Java多线程--线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...

  7. java多线程 线程安全_Java中的线程安全

    java多线程 线程安全 Thread Safety in Java is a very important topic. Java provides multi-threaded environme ...

  8. java多线程-线程的停止【interrupt】

    java多线程-线程的停止 文章目录 java多线程-线程的停止 线程停止的原理 如何正确停止线程 在普通情况下停止线程 代码展示 在阻塞情况下停止线程 代码展示 线程在每次迭代后都阻塞 代码展示 停 ...

  9. servlet单实例多线程 ---线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。(所有建议不要在servlet中定义成员变

    Servlet 单例多线程 Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servl ...

  10. Java多线程 ——线程基础和锁锁锁

    Java多线程(一) 一.线程的定义 二.Synchronize线程同步 三.偏向锁.自旋锁.重量级锁 四.volatile关键字 4.1.普通变量运算的物理意义 4.2.有无解决的方案 4.3.vo ...

最新文章

  1. 4月23日遇到的问题
  2. web 点击劫持 X-Frame-Options
  3. 文巾解题 1310. 子数组异或查询
  4. 20 条非常实用的 Python 代码,建议收藏!
  5. PHP微信支付没有收到微信的回调怎么修改订单状态:主动查询
  6. 深度学习笔记——基于传统机器学习算法(LR、SVM、GBDT、RandomForest)的句子对匹配方法
  7. Django中session和cookie简单的使用
  8. 将经过身份验证的用户注入Spring MVC @Controllers
  9. 基于matlab的信号与系统实例,华南理工大学信号与系统实验基于Matlab的信号处理实例...
  10. python之字典的操作
  11. CSS详解(一)——CSS基本原理
  12. pmp学习资料下载-pmp备考
  13. LM小型可编程控制器软件(基于CoDeSys)笔记二十七:温度电阻通道和DO通道
  14. Linux树莓派实战案例论文,树莓派|树莓派使用实例之:2 Pi R
  15. TryHackMe-Misguided Ghosts(boot2root)
  16. 【深度学习】Github 最受欢迎的深度学习项目 TOP 20
  17. web应用F12查看报错(前后端bug判断、2XX/3XX/4XX/5XX常见状态码解析)
  18. PDF→Excel格式转换工具集锦
  19. 技术分享1: jinkens构建Android工程,并上传到蒲公英平台
  20. gateway的官方文档解读

热门文章

  1. C语言 指针+二维数组详解 (应付期末、考研的最强笔记,建议收藏)
  2. 并查集——家谱(洛谷 P2814)
  3. 深层神经网络——线性模型的局限性
  4. 计算机科学与技术专业热,广东省计算机科学与技术专业最“热”
  5. mysql讀取sql_MySQL数据库之python json及mysql读取json文件存sql等问题
  6. 那些年删过的库,跑过的路,你从中找到解决方法了吗?
  7. 分盘存储:实现数据库备集群备份文件分散存储
  8. Volcano 监控设计解读,一看就懂
  9. 懂分析、会预测,你见过这样的华为云DAS吗?
  10. 昇腾AI处理器软件栈--运行管理器(Runtime)