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

【高级编程】synchronized 解决并发问题 类的线程安全类型

文章目录

    • 并发问题
      • 同步方法
      • 同步代码块
    • 线程安全类型
      • ArrayList
      • Hashtable
      • HashMap
      • Vector

多线程共享数据引发的问题

模拟 “A” “B” “C” 三人抢票,总票数10张,打印抢票情况以及剩余票数。

public class Site implements Runnable {int count = 10; // 总票数int num = 0;    // 已抢票数@Overridepublic void run() {while (true) {if (count <= 0) {break;}count--;num++;System.out.println(Thread.currentThread().getName() + "抢到第" + num + "张票,剩余" + count + "张票!");//休眠  模拟网络延时try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();
}}}}
public static void main(String[] args) {Site site = new Site();Thread th1 = new Thread(site,"A");Thread th2 = new Thread(site,"B");Thread th3 = new Thread(site,"C");th1.start();th2.start();th3.start();
}

问题

  • 不是从第1张票开始

  • 存在多人抢到一张票的情况

  • 有些票号没有被抢到

多个线程操作同一共享资源时,将引发数据不安全问题

并发问题

synchronized 在 Java 中是一种悲观锁(Pessimistic Lock)的形式。悲观锁假设最坏的情况,即认为数据总是会被其他线程修改,因此在处理数据之前就先获取锁。这样可以避免数据冲突,但也可能导致较高的竞争开销。

同步方法

使用 synchronized 修饰的方法控制对类成员变量的访问,synchronized 就是为当前的线程声明一把锁

访问修饰符 synchronized 返回类型 方法名(参数列表){……}

synchronized 访问修饰符 返回类型 方法名(参数列表){……}

使用同步方法的网络购票

public class Site implements Runnable{int count = 10; // 总票数int num = 0;    // 已抢票数@Overridepublic void run() {while(true){if(qg()){ break; }//休眠  模拟网络延时try {Thread.sleep(500); // 休眠半秒} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized boolean qg(){if(count <= 0){ return true; }count--;num++;System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!");return false;}}

同步代码块

使用 synchronized 关键字修饰的代码块

synchronized(syncObject){// 需要同步的代码
}
  • syncObject 为需同步的对象,通常为 this
  • 效果与同步方法相同

使用同步代码块的网络购票

public class Site implements Runnable{int count = 10; // 总票数int num = 0;    // 已抢票数@Overridepublic void run() {while(true){//同步synchronized (this){if(count <= 0){ break;}count--;num++;System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!");}//休眠  模拟网络延时try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();
}}}}

多个并发线程访问同一资源的同步代码块时

  • 同一时刻只能有一个线程进入同步代码块

  • 当一个线程访问一个同步代码块时,其他同步代码块同样被锁定

  • 当一个线程访问一个同步代码块时,其他线程可以访问该资源的非同步代码

线程安全类型

为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型

方法是否同步效率比较适合场景
线程安全多线程并发共享资源
非线程安全单线程
HashtableHashMap
继承关系实现了 Map 接口,继承 Dictionary实现了 Map 接口,继承 AbstractMap
安全性线程安全,效率较低非线程安全,效率较高
键值键和值都不允许为 null键和值都允许为 null
StringBufferStringBuilder
安全性线程安全非线程安全
适合场景适用于多线程环境中的字符串大量操作适用于单线程环境中的字符串拼接

ArrayList

非线程安全

// 查看 ArrayList 类的 add() 方法定义
public boolean add(E e) {ensureCapacityInternal(size + 1); // 集合扩容,确保能新增数据elementData[size++] = e; // 在新增位置存放数据return true;
}

ArrayList 类的 add() 方法为非同步方法。当多个线程向同一个 ArrayList 对象添加数据时,可能出现数据不一致问题

Hashtable

线程安全

Hashtable<String,String> hashtable = new Hashtable<>();
hashtable.put("","");public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) {throw new NullPointerException();}// Makes sure the key is not already in the hashtable.......
}

HashMap

非线程安全

HashMap:在多线程环境中,可能会导致数据丢失或结构破坏。

HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("","");public V put(K key, V value) {return putVal(hash(key), key, value, false, true);
}

Vector

线程安全

Vector vector = new Vector();
vector.add("");public synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;
}

相关文章:

【高级编程】synchronized 解决并发问题 类的线程安全类型

文章目录 并发问题同步方法同步代码块 线程安全类型ArrayListHashtableHashMapVector 多线程共享数据引发的问题 模拟 “A” “B” “C” 三人抢票&#xff0c;总票数10张&#xff0c;打印抢票情况以及剩余票数。 public class Site implements Runnable {int count 10; // …...

Speculative RAG:为知识密集型数据服务的RAG

论文链接 RAG的一个棘手问题是不知道该召回多少chunk&#xff0c;少了可能丢信息&#xff0c;多了会引入噪声信息。虽然有self-reasoning等自我反思的解决办法&#xff0c;但是整体链路太长&#xff0c;延迟高&#xff0c;不利于工业落地。 虽然无法面对整个服务场景&#xff…...

[Go]-抢购类业务方案

文章目录 要点&#xff1a;1. 抢购/秒杀业务的关键挑战2. 技术方案3.关键实现点4.性能优化建议5.其他考虑因素 细节拆分&#xff1a;1. **高并发处理**2.**限流与防护**3.**库存控制**4. **异步处理**5. **数据一致性**6. **常用架构设计**7. **代码示例**8. 进一步优化9. 注意…...

Android 源码多个Launcher设置默认Launcher

目录 第一部分、android10之前 一.多个launcher 启动设置默认launcher的核心类 二 在自定义服务里面设置默认Launcher 第二部分、android10之后 一、Launcher应用内置并设置为默认Launcher 1.通过ResolverActivity.java设置为默认Launcher 改法一&#xff1a; 改法二&am…...

计算机毕业设计 网上体育商城系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

深度学习中实验、观察与思考的方法与技巧

在深度学习中&#xff0c;实验、观察与思考是理解和改进模型性能的关键环节。以下是一些有效的方法与技巧&#xff0c;可以帮助你在深度学习实践中系统性地开展实验、分析结果并进行深入思考&#xff1a; 1. 明确实验目标 在开始实验前&#xff0c;确保对实验的目标有清晰的定…...

记一次 FastDFS 存储节点迁移:基于 scp 的实践与经验分享

一、背景 某某项目&#xff0c;机房到期&#xff0c;需要迁移至其他机房&#xff1b; 此项目已经运行了3年多&#xff0c;fastdfs累计数据大概在250G 左右&#xff0c;现需要把旧的fastdfs数据迁移到新的fastdfs上&#xff1b; 采用scp物理迁移数据的方式&#xff0c;停机迁移…...

http连接github远程仓库密码问题解决办法

目录 一、问题&#xff1a;使用http连接失败 二、解决办法&#xff1a;使用个人访问令牌。 1、生成访问令牌&#xff1a; 步骤 1: 登录 GitHub 步骤 2: 进入设置页面 步骤 3: 生成新的访问令牌 步骤 4: 配置访问令牌 步骤 5: 复制令牌 2. 使用访问令牌 一、问题&#…...

LAMP环境下项目部署

目录 目录 1、创建一台虚拟机 centos 源的配置 备份源 修改源 重新加载缓存 安装软件 2、关闭防火墙和selinux 查看防火墙状态 关闭防火墙 查看SELinux的状态 临时关闭SELinux 永久关闭SELinux&#xff1a;编辑SELinux的配置文件 配置文件的修改内容 3、检查系统…...

Visual Studio 2022从外部引入dll导致的问题

这里以我学MapGIS二次开发的一个小demo为例 一、如何引入dll 1、在解决方案资源管理器中&#xff0c;有个引用的选项 2、然后右键点击添加引用 点击之后会出现如下&#xff1a; 3、点击浏览选项&#xff0c;选择想要引入dll的路径&#xff0c;这里我选择下载MapGIS 10的路径 …...

大模型从失败中学习 —— 微调大模型以提升Agent性能

人工智能咨询培训老师叶梓 转载标明出处 以往的研究在微调LLMs作为Agent时&#xff0c;通常只使用成功的交互轨迹&#xff0c;而丢弃了未完成任务的轨迹。这不仅造成了数据和资源的浪费&#xff0c;也可能限制了微调过程中可能的优化路径。论文《Learning From Failure: Integ…...

10.web应用体系以及windows网络常见操作应用

一、Dos命令 1.启动方式&#xff1a;winR&#xff0c;输入cmd 2.切换盘符/路径&#xff1a;盘符名称&#xff1a; &#xff08;C:) cd 目录 &#xff08;cd B111&#xff09;&#xff08;目录名按table键自动补全&#xff09; 3.查看目录&#xff1a;dir dir /p 分页展示目录及…...

【数据结构与算法 | 灵神题单 | 前后指针(链表)篇】力扣19, 61,1721

1. 力扣19&#xff1a;删除链表的倒数第N个节点 1.1 题目&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; …...

机器学习之实战篇——MNIST手写数字0~9识别(全连接神经网络模型)

机器学习之实战篇——Mnist手写数字0~9识别&#xff08;全连接神经网络模型&#xff09; 文章传送MNIST数据集介绍&#xff1a;实验过程实验环境导入模块导入MNIST数据集创建神经网络模型进行训练&#xff0c;测试&#xff0c;评估模型优化 文章传送 机器学习之监督学习&#…...

ICLR2024: 大视觉语言模型中对象幻觉的分析和缓解

https://arxiv.org/pdf/2310.00754 https://github.com/YiyangZhou/LURE 背景 对象幻觉&#xff1a;生成包含图像中实际不存在的对象的描述 早期的工作试图通过跨不同模式执行细粒度对齐&#xff08;Biten et al.&#xff0c;2022&#xff09;或通过数据增强减少对象共现模…...

数据库系统 第54节 数据库优化器

数据库优化器是数据库管理系统&#xff08;DBMS&#xff09;中的一个关键组件&#xff0c;它的作用是分析用户的查询请求&#xff0c;并生成一个高效的执行计划。这个执行计划定义了如何访问数据和执行操作&#xff0c;以最小化查询的执行时间和资源消耗。以下是数据库优化器的…...

微服务杂谈

几个概念 还是第一次听说Spring Cloud Alibaba &#xff0c;真是孤陋寡闻了&#xff0c;以前只知道 SpringCloud 是为了搭建微服务的&#xff0c;spring boot 则是快速创建一个项目&#xff0c;也可以是一个微服务 。那么SpringCloud 和 Spring boot 有什么区别呢&#xff1f;S…...

【Pandas操作2】groupby函数、pivot_table函数、数据运算(map和apply)、重复值清洗、异常值清洗、缺失值处理

1 数据清洗 #### 概述数据清洗是指对原始数据进行处理和转换&#xff0c;以去除无效、重复、缺失或错误的数据&#xff0c;使数据符合分析的要求。#### 作用和意义- 提高数据质量&#xff1a;- 通过数据清洗&#xff0c;数据质量得到提升&#xff0c;减少错误分析和错误决策。…...

如何分辨IP地址是否能够正常使用

在互联网的日常使用中&#xff0c;无论是进行网络测试、网站访问、数据抓取还是远程访问&#xff0c;一个正常工作的IP地址都是必不可少的。然而&#xff0c;由于各种原因&#xff0c;IP地址可能无法正常使用&#xff0c;如被封禁、网络连接问题或配置错误等。本文将详细介绍如…...

Sqoop 数据迁移

Sqoop 数据迁移 一、Sqoop 概述二、Sqoop 优势三、Sqoop 的架构与工作机制四、Sqoop Import 流程五、Sqoop Export 流程六、Sqoop 安装部署6.1 下载解压6.2 修改 Sqoop 配置文件6.3 配置 Sqoop 环境变量6.4 添加 MySQL 驱动包6.5 测试运行 Sqoop6.5.1 查看Sqoop命令语法6.5.2 测…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...