山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(十八)- JUC(4)

线程安全分析

成员变量和静态变量是否线程安全?

  1. 如果它们没有共享,则线程安全

  2. 如果它们被共享了,根据它们的状态是否能够改变,又分两种情况

    如果只有读操作,则线程安全如果有读写操作,则这段代码是临界区,需要考虑线程安全共享且有读写操作不一定安全。

局部变量是否线程安全?

局部变量是线程安全的

但局部变量引用的对象则未必

​ 如果该对象没有逃离方法的作用访问,它是线程安全的

​ 如果该对象逃离方法的作用范围,需要考虑线程安全

常见线程安全类

  1. Integer

  2. HashTable

  3. String

  4. Rando

  5. Vector

  6. JUC下的类

它们单个方法是线程安全的,但是如果多个方法组合的时候就不一样了。下面的代码出现的问题就是线程1判断成功之后切换,刚好释放了锁,然后就是线程2获取锁进行判断,再次切换线程1获取锁处理put,切换线程2也可以获取锁处理put。因为单个方法执行完就会释放锁。所以这样还是需要整体上加锁才能够继续处理

不可变类线程安全

StringString和Integer都是不可变的,String本质上就是一个char[]数组。如果是substring方法实际上就是复制一个新的数组出来,然后再给String的char数组进行赋值。replace也实际上只是创建数组,然后对比原数组的旧值,如果是旧值那么直接给新的数组的那个位置赋值新值

卖票案例

  @Slf4j(topic = "c.ExerciseSell")public class Test {public static void main(String[] args) throws InterruptedException {// 模拟多人买票TicketWindow window = new TicketWindow(1000);​// 所有线程的集合List<Thread> threadList = new ArrayList<>();​// 卖出的票数统计List<Integer> amountList = new Vector<>();​for (int i = 0; i < 2000; i++) {Thread thread = new Thread(() -> {// 买票try {Thread.sleep(random(10));} catch (InterruptedException e) {e.printStackTrace();}int amount = window.sell(random(5));// 统计买票数amountList.add(amount);});threadList.add(thread);thread.start();}​// 等所有线程执行结束for (Thread thread : threadList) {thread.join();}​// 统计卖出的票数和剩余票数log.debug("余票:{}",window.getCount());log.debug("卖出的票数:{}", amountList.stream().mapToInt(i-> i).sum());}​// Random 为线程安全static Random random = new Random();​// 产生随机 1~5public static int random(int amount) {return random.nextInt(amount) + 1;}}​// 售票窗口class TicketWindow {private int count;​public TicketWindow(int count) {this.count = count;}​// 获取余票数量public int getCount() {return count;}​// 售票 synchronizedpublic  int sell(int amount) {if (this.count >= amount) {this.count -= amount;return amount;} else {return 0;}}}

解决 :

  // 售票 synchronizedpublic synchronized int sell(int amount) {if (this.count >= amount) {this.count -= amount;return amount;} else {return 0;}}

转账案例

  @Slf4j(topic = "c.ExerciseTransfer")public class ExerciseTransfer {public static void main(String[] args) throws InterruptedException {Account a = new Account(1000);Account b = new Account(1000);Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {a.transfer(b, randomAmount());}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {b.transfer(a, randomAmount());}}, "t2");t1.start();t2.start();t1.join();t2.join();// 查看转账2000次后的总金额log.debug("total:{}", (a.getMoney() + b.getMoney()));}​// Random 为线程安全static Random random = new Random();​// 随机 1~100public static int randomAmount() {return random.nextInt(100) + 1;}}​// 账户class Account {private int money;​public Account(int money) {this.money = money;}​public int getMoney() {return money;}​public void setMoney(int money) {this.money = money;}​// 转账public void transfer(Account target, int amount) {synchronized(Account.class) {if (this.money >= amount) {this.setMoney(this.getMoney() - amount);target.setMoney(target.getMoney() + amount);}}}}

Moniter

Java对象头

包括了markword主要就是存储hashcode,age(gc生命值),biase_lock是不是偏向锁,01加锁的情况

还有就是klassword只要就是指向类对象(类的信息)。

如果是数组那么就还包括了数组的长度。

Moniter(锁)

Thread1此时进入阻塞队列

工作原理

实际上就是把obj的markword前面30bit记录monitor的地址,指向monitor。然后如果有线程要执行临时区的时候那么就把monitor的owner指向对应的线程。如果又有线程进来,那么会看看obj是否关联锁,然后再看看锁是否有owner,如果有那么就进入到EntryList阻塞等待。等待线程释放锁之后,唤醒entryList然后重新开始竞争。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/14906.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java之设计模式

概述 设计模式就是经过我们开发人员通过长时间的开发实践得出的一种开发模式,目的就是在开发过程中降低代码耦合度,提高代码可复用性/扩展/维护。目前主要有23种设计模式,分为创建型模式、行为型模式、结构型模式。本文列举了实际项目中使用到的设计模式,包括单例模式、策略模…

分布式和集群区别

分布式 分布式的主要工作是分解任务&#xff0c;将职能拆解&#xff0c;多个人在一起做不同的事 集群 集群主要是将同一个业务&#xff0c;部署在多个服务器上 &#xff0c;多个人在一起做同样的事

GPT-3:自然语言处理的预训练模型

自然语言处理&#xff08;NLP&#xff09;领域近年来取得了显著的进步&#xff0c;特别是预训练模型的引入&#xff0c;彻底改变了我们与计算机交互和处理自然语言的方式。在这些模型中&#xff0c;GPT-3&#xff08;Generative Pre-trained Transformer 3&#xff09;无疑是最…

Spring常见注解

Spring常见注解 1. 概述2. DI&#xff08;依赖注⼊&#xff09;相关注解2.1 Autowired2.2 Bean2.3 Qualifier2.4 Required &#xff08;很少使用&#xff09;2.5 Value2.6 Lazy2.7 Profile 1. 概述 我们都知道Spring最核心的特性就是IOC&#xff08;控制反转&#xff09; AOP&…

PySODEvalToolkit 使用笔记

1. 克隆仓库 首先&#xff0c;克隆PySODEvalToolkit仓库到你的本地机器&#xff1a; git clone https://github.com/lartpang/PySODEvalToolkit.git2. 创建虚拟环境 cd PySODEvalToolkit conda create -n pysodeval python3.73. 安装依赖 pip install -r requirements.txt4…

[算法] 优先算法(一): 双指针算法(上)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

SpringBoot2.0.x旧版集成Swagger UI报错Unable to infer base url...解决办法

一、问题描述 1.1项目背景 SpringBoot2.0.9的旧版项目维护开发&#xff0c;集成Swagger-ui2.9.2无法访问的问题。不用想啊&#xff0c;这种老项目是各种过滤器拦截器的配置&#xff0c;访问不到&#xff0c;肯定是它们在作妖。懂得都懂啊&#xff0c;这里交给大家一个排错的办…

Flutter设计模式全面解析:单例模式

谈到设计模式这个“古老”的话题&#xff0c;大家先别急着划走哈&#xff0c;虽然对它再熟悉不过&#xff0c;几乎是最初开始学习编程到现在伴随着我们整个编程生涯&#xff0c;最早 Java、C 语言实现的各种设计模式到现在还会经常有所接触&#xff0c;面试中也是必问的环节&am…

Adobe Camera Raw 11 for Mac/win:摄影后期处理的革命性飞跃

在数字摄影的世界里&#xff0c;RAW格式以其未压缩的原始数据特性&#xff0c;为摄影师提供了更大的后期处理空间。而Adobe Camera Raw 11&#xff0c;作为这一领域的翘楚&#xff0c;以其卓越的性能和创新的功能&#xff0c;为摄影师们带来了前所未有的创作体验。 Adobe Came…

LeetCode450删除二叉搜索树中的节点

题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。一般来说&#xff0c;删除节点可分为两个步骤&#xff1…

Linux环境中部署docker私有仓库Registry与远程访问详细流程

目录 前言 1. 部署Docker Registry 2. 本地测试推送镜像 3. Linux 安装cpolar 4. 配置Docker Registry公网访问地址 5. 公网远程推送Docker Registry 6. 固定Docker Registry公网地址 前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊…

网络安全知识核心20要点

1、什么是SQL注入攻击 概述 攻击者在 HTTP 请求中注入恶意的 SQL 代码&#xff0c;服务器使用参数构建数据库 SQL 命令时&#xff0c;恶意SQL 被一起构造&#xff0c;并在数据库中执行。 注入方法 用户登录&#xff0c;输入用户名 lianggzone&#xff0c;密码‘ or ‘1’’…

揭秘Python的魔法:装饰器的超能力大揭秘 ‍♂️✨

文章目录 Python进阶之装饰器详解1. 引言装饰器的概念与意义装饰器在Python编程中的作用 2. 背景介绍2.1 函数作为对象2.2 高阶函数 3. 装饰器基础3.1 理解装饰器3.2 装饰器的工作原理 4. 带参数的装饰器4.1 为什么需要带参数4.2 实现带参数的装饰器使用函数包裹装饰器使用类实…

TypeScript-泛型

泛型(Generics) 指在定义接口&#xff0c;函数等类型的时候&#xff0c;不预先指定具体的类型&#xff0c;而在使用的时候再指定类型的一种特性&#xff0c;使用泛型可以复用类型并且让类型更加灵活 泛型接口-interface 语法&#xff1a;在 interface 接口类型的名称后面使用…

AI服务器连接解决方案领军企业Astera Labs宣布,将在台湾组建首个位于硅谷以外的Cloud-Scale Interop Lab

AI服务器连接解决方案领军企业Astera Labs宣布&#xff0c;将在台湾组建首个位于硅谷以外的Cloud-Scale Interop Lab&#xff0c;集结中国台湾制造商共同参与。据《工商时报》报道&#xff0c;Astera Labs将与台湾主要ODM客户紧密合作&#xff0c;预期广达、英业达、纬创资通、…

web前端的路径和Servlet注解开发

目录 在web前端的两种路径 绝对路径的两种写法 相对路径 相对路径进阶 使用注解开发Servlet 使用注解开发Servlet的注意事项 使用idea创建servlet模板 在web前端的两种路径 绝对路径的两种写法 1.带网络三要素 http://ip地址:端口号/资源路径 2.不带网络三要素 /资源路…

『哈哥赠书 - 53期』-『深入浅出 Spring Boot 3.x』

⭐️ 《深入浅出 Spring Boot 3.x》 ⭐️ 学习Spring Boot的必读之书 在 Java 后端开发领域&#xff0c;功能强大的 Spring 开源框架不仅是首选&#xff0c;也是事实上的标准。但由于 Spring 存在配置烦琐、部署不易、依赖管理困难等问题&#xff0c;因此基于 Spring 的快速开…

告别传统,拥抱未来——上门回收小程序引领变革

随着科技的飞速发展&#xff0c;我们生活的方方面面都在经历着前所未有的变革。在环保和可持续发展的背景下&#xff0c;传统的废品回收方式已经难以满足现代社会的需求。而上门回收小程序的出现&#xff0c;正以其便捷、高效的特点&#xff0c;引领着废品回收行业的变革。 一、…

【NLPl练习】Transformer起源与发展

Transformer总结 Transformer模型类别分为&#xff1a; 纯Encoder模型纯Decoder模型Encoder-Decoder模型 Transformer模型的本质是预训练语言模型&#xff0c;首先采用自监督学习的方式在大量生语料库上训练&#xff0c;无需人工标注。常用的预训练任务主要有以下两个&#xff…

力扣343 整数拆分 Java版本

文章目录 题目描述代码 题目描述 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输…