当前位置: 首页 > news >正文

重学java 39.多线程 — 线程安全

逐渐成为一个情绪稳定且安静成长的人

                                                       ——24.5.24

线程安全

什么时候发生?

       当多个线程访问同一个资源时,导致了数据有问题,出现并发问题,数据不能及时更新,导致数据发生错误,出现线程安全问题

多线程安全问题示例

package S71ThreadSafe;public class MyTicket implements Runnable{// 定义100章票int ticket = 100;@Overridepublic void run(){while(true){if(ticket>0){System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");ticket--;}}}
}
package S71ThreadSafe;public class Demo210Test {public static void main(String[] args) {// new一次,分别传递到三个线程对象中去MyTicket myTicket = new MyTicket();Thread th1= new Thread(myTicket, "赵四");Thread th2= new Thread(myTicket, "刘能");Thread th3= new Thread(myTicket, "广坤");th1.start();th2.start();th3.start();}
}

解决线程安全问题方式一:同步代码块

synchronized代码块 == 上锁 可以解决线程安全问题,不保证线程顺序

1.格式:

        synchronized(任意接收对象){

               线程要执行的语句;

        }

2.任意对象:

        就是我们的锁对象

3.执行:

        一个线程拿到锁之后,会进入到同步代码块中执行,在此期间,其他线程拿不到锁,就进不去同步代码块。需要在同步代码块外面等待排队,需要等待执行的线程执行完毕,出了同步代码块,相当于释放锁了,等待的线程才能抢到锁,才能进入到同步代码块中执行,上的锁必须是同一个锁对象,同一把锁

package S71ThreadSafe;import java.util.Scanner;public class MyTicket implements Runnable{// 定义100章票int ticket = 100;// 任意new一个对象Object obj = new Object();Scanner sc = new Scanner(System.in);@Overridepublic void run(){while(true){synchronized (sc) {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");ticket--;}}}}
}
package S71ThreadSafe;public class Demo210Test {public static void main(String[] args) {// new一次,分别传递到三个线程对象中去MyTicket myTicket = new MyTicket();Thread th1= new Thread(myTicket, "赵四");Thread th2= new Thread(myTicket, "刘能");Thread th3= new Thread(myTicket, "广坤");th1.start();th2.start();th3.start();}
}

解决线程安全问题方式二:同步方法

1.普通同步方法_非静态

        在普通方法内用一个同步代码块

① 格式:

        修饰符 synchronized 返回值类型 方法名(参数){

                方法体
                return 结果

        }

② 默认锁:

        this

package S73ThreadSafeSolve2;public class Demo212Test {public static void main(String[] args) {// new一次,分别传递到三个线程对象中去MyTicket myTicket = new MyTicket();System.out.println(myTicket);Thread th1= new Thread(myTicket, "赵四");Thread th2= new Thread(myTicket, "刘能");Thread th3= new Thread(myTicket, "广坤");th1.start();th2.start();th3.start();}
}
package S73ThreadSafeSolve2;import java.util.Scanner;public class MyTicket implements Runnable{// 定义100章票int ticket = 100;Scanner sc = new Scanner(System.in);@Overridepublic void run(){while(true){try{Thread.sleep(100L);} catch (InterruptedException e) {throw new RuntimeException(e);}// 调用同步方法// method01();method02();}}// 定义一个同步方法public synchronized void method01(){if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");ticket--;}}// 在普通方法内用一个同步代码块public void method02(){synchronized (this){System.out.println(this+"————————————————————");if (ticket>0){System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");ticket--;}}}}

       只new了一次对象

2.静态同步方法

① 格式

        修饰符 static synchronized 返回值类型 方法名(参数){

                方法体
                return 结果

        }

② 默认锁

        class对象

package S74ThreadSafeSolve3;import java.util.Scanner;public class MyTicket implements Runnable{// 定义100章票static int ticket = 100;Scanner sc = new Scanner(System.in);@Overridepublic void run(){while(true){try{Thread.sleep(100L);} catch (InterruptedException e) {throw new RuntimeException(e);}// 调用同步方法method02();}}// 在普通方法内用一个同步代码块public static void method02(){synchronized (MyTicket.class){if (ticket>0){System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");ticket--;}}}}
package S74ThreadSafeSolve3;public class Demo213Test {public static void main(String[] args) {// new一次,分别传递到三个线程对象中去MyTicket myTicket = new MyTicket();System.out.println(myTicket);Thread th1= new Thread(myTicket, "赵四");Thread th2= new Thread(myTicket, "刘能");Thread th3= new Thread(myTicket, "广坤");th1.start();th2.start();th3.start();}
}

StringBuider是线程不安全的,StringBuffer加了死锁是线程安全,线程同步的

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 一篇文章讲透排序算法之希尔排序
  • 大摩:AI PC渗透率到2028年将达65%,联想和戴尔是最大受益者
  • 【linux】docker下nextcloud安装人脸识别插件
  • 碌时刻必备!微信自动回复让你告别消息堆积
  • 临时存储和永久存储的区别
  • HarmonyOS 鸿蒙应用开发 - 多态样式 stateStyles
  • solidworks画螺栓学习笔记
  • 自己手写一个栈【C风格】
  • Qml:线程
  • 93.网络游戏逆向分析与漏洞攻防-游戏技能系统分析-增强技能信息显示后进行分析
  • Redis批量删除指定前缀的key
  • STM32H743的FDCAN使用方法(2):STM32CubeMX初始化代码修改
  • 判断变量是否为数组的几种方法
  • 音视频及H264/H256编码相关原理
  • 关于Broken pipe异常的一点学习记录
  • 自己简单写的 事件订阅机制
  • [译] React v16.8: 含有Hooks的版本
  • github从入门到放弃(1)
  • HTTP中GET与POST的区别 99%的错误认识
  • Java程序员幽默爆笑锦集
  • JDK9: 集成 Jshell 和 Maven 项目.
  • jquery ajax学习笔记
  • JS基础之数据类型、对象、原型、原型链、继承
  • magento2项目上线注意事项
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Python中eval与exec的使用及区别
  • ubuntu 下nginx安装 并支持https协议
  • Vim Clutch | 面向脚踏板编程……
  • vue-cli3搭建项目
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 基于 Babel 的 npm 包最小化设置
  • 讲清楚之javascript作用域
  • 驱动程序原理
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 我看到的前端
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 智能合约Solidity教程-事件和日志(一)
  • MyCAT水平分库
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​Linux·i2c驱动架构​
  • ​MySQL主从复制一致性检测
  • ​Python 3 新特性:类型注解
  • # wps必须要登录激活才能使用吗?
  • (4.10~4.16)
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (多级缓存)多级缓存
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)Google的Objective-C编码规范