【多线程】线程安全与线程同步
线程安全与线程同步
1.什么是线程安全问题?
多个线程同时操作同一个共享资源的时候,可能会出现业务安全问题
取钱的线程安全问题场景:
两个人他们有一个共同的账户,余额是10万元,如果两个人同时来取钱,并且2人各自都在取钱10万元,可能会出现什么问题?
(1)线程安全问题出现的原因:
- 存在多个线程在同时执行
- 同时访问一个共享资源
- 存在修改该共享资源
2.线程同步
线程同步就是解决线程安全问题的方案
(1)线程同步的思想:让多个线程实现先后依次访问共享资源,这样就解决了安全问题
(2)线程同步的常见方案
- 加锁:每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动解锁,然后其他线程才能再加锁进来
(3)线程同步方式
-
方式一:同步代码块
①作用:把访问共享资源的核心代码给上锁,以此保证线程的安全
②原理:每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行
③同步锁的注意事项:对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则会出bug
④锁对象不能随便选择一个唯一的对象,会影响其他无关线程的执行,例如String字符串
⑤锁对象的使用规范
- 建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象
- 对于静态方法建议使用字节码(类名.class)对象作为锁对象
public class Demo {public static void main(String[] args) {//3、创建账户对象(共享数据)Account acc = new Account("9527", 100000);//4、两个线程同时取款(多个线程操作共享数据,出现线程安全问题)new MyThread(acc, "小明").start();new MyThread(acc, "小红").start();}
}
//2、线程类,封装取款的代码
class MyThread extends Thread {private Account acc;public MyThread(Account acc, String name) {super(name);this.acc = acc;}@Overridepublic void run() {//取钱时,要传递取款金额acc.drawMoney(100000);}
}//1、账户类,包含取款功能
class Account {//卡号private String cardID;//余额private double money;public Account() {}public Account(String cardID, double money) {this.cardID = cardID;this.money = money;}public String getCardID() {return cardID;}public void setCardID(String cardID) {this.cardID = cardID;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}//取款功能,参数money为取款金额public void drawMoney(double money) {//获取当前线程对象的名称String name = Thread.currentThread().getName();synchronized (this) {if (this.money >= money) {System.out.println(name + "取钱:" + money + "成功");this.money -= money;System.out.println(name + "取钱后余额为:" + this.money);} else {System.out.println(name + "取钱失败,余额不足");}}}//对于静态方法建议使用字节码(类名.class)对象作为锁对象public static void test(){synchronized (Account.class){}}
}
-
方式二:同步方法
①作用:把访问共享资源的核心方法上锁,以此保证线程安全
②原理:每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行
③同步方法的底层原理
- 同步方法其实底层也是由隐式锁对象的,只是锁的范围是整个方法代码
- 如果方法是实例方法:同步方法默认this作为锁的对象
- 如果方法是静态方法:同步方法默认用类名.class作为锁对象
//线程类和测试类同上
//1、账户类,包含取款功能
class Account {//卡号private String cardID;//余额private double money;public Account() {}public Account(String cardID, double money) {this.cardID = cardID;this.money = money;}public String getCardID() {return cardID;}public void setCardID(String cardID) {this.cardID = cardID;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}//取款功能,参数money为取款金额public synchronized void drawMoney(double money) {String name = Thread.currentThread().getName();if (this.money >= money) {System.out.println(name + "取钱:" + money + "成功");this.money -= money;System.out.println(name + "取钱后余额为:" + this.money);} else {System.out.println(name + "取钱失败,余额不足");}}//静态方法public synchronized static void test(){}
}
④同步代码块和同步方法的区别
同步代码块:锁对象可以指定,锁的范围可以指定,性能高且灵活
同步方法:锁对象不能指定,锁的是方法体,阅读性更高
-
方式三:Lock锁
①Lock锁是JDK5开始提供的一个新的锁定操作,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便、更强大
②Lock是接口,不能直接被实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象
public ReentrantLock():获得Lock锁的实现类对象
③Lock的常用方法
- void lock():获得锁
- void unlock():释放锁
④Lock锁使用规范
- 锁对象创建在成员位置,使用final修饰
- 释放锁的代码写在finally块中
public class Demo {public static void main(String[] args) {//3、创建账户对象(共享数据)Account acc = new Account("9527", 100000);//4、两个线程同时取款(多个线程操作共享数据,出现线程安全问题)new MyThread(acc, "小明").start();new MyThread(acc, "小红").start();} } //2、线程类,封装取款的代码 class MyThread extends Thread {private Account acc;public MyThread(Account acc, String name) {super(name);this.acc = acc;}@Overridepublic void run() {//取钱时,要传递取款金额acc.drawMoney(100000);} } //1、账户类,包含取款功能 class Account {//卡号private String cardID;//余额private double money;//规范1、锁对象创建在成员位置,使用final修饰private final ReentrantLock lock = new ReentrantLock();public Account() {}public Account(String cardID, double money) {this.cardID = cardID;this.money = money;}public String getCardID() {return cardID;}public void setCardID(String cardID) {this.cardID = cardID;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}//取款功能,参数money为取款金额public void drawMoney(double money) {String name = Thread.currentThread().getName();try {//上锁lock.lock();if (this.money >= money) {System.out.println(name + "取钱:" + money + "成功");this.money -= money;System.out.println(name + "取钱后余额为:" + this.money);} else {System.out.println(name + "取钱失败,余额不足");}} catch (Exception e) {e.printStackTrace();} finally {//释放锁lock.unlock();}} }
相关文章:

【多线程】线程安全与线程同步
线程安全与线程同步 1.什么是线程安全问题? 多个线程同时操作同一个共享资源的时候,可能会出现业务安全问题 取钱的线程安全问题场景: 两个人他们有一个共同的账户,余额是10万元,如果两个人同时来取钱,…...
指针权限,new与delete,类与对象,函数模板,类模板的用法
指针权限 用法 void Print(const char* SecretPointer) {cout << "绝密指令为:";cout << SecretPointer << endl; }void Change(int& number, int* const FixedPointer) {cout << "更换站台数字为:";c…...
Unity——脚本与序列化
在介绍序列化之前,我们先来了解一下为什么要对数据进行序列化 数据序列化有以下几个主要的应用场景和目的: 1. 持久化存储:序列化可以将对象或数据结构转换为字节序列,使得其可以被存储在磁盘上或数据库中。通过序列化ÿ…...
NJ求职盘点
电子显示 集成电路 地平线 后摩智能 芯启源 自动驾驶 地平线 栖霞区兴智科技园 泊车、SLAM/3D算法工程师 https://wecruit.hotjob.cn/SU64819a4f2f9d2433ba8b043a/pb/social.html?currentPage1 后摩智能 栖霞区兴智科技园 视觉感知算法资深工程师 可以做自动驾驶前瞻性…...
01卡特兰数
卡特兰数跟排列组合很有关系,所以在看此文章前请掌握: 加法原理乘法原理A(m,n)计算公式及其原理C(m,n)计算公式及其原理 前言 今天您将会学习到基本的卡特兰数及其应用。 一、卡特兰数是什么? 卡特兰数(Catalan number࿰…...

若依前端vue设置子路径
若依前端vue设置子路径 说明:本文档中以前后端分离版为例,版本为:3.8.6 一设置变量 在.env.development和.env.production 中定义一个变量如VUE_APP_PROJECT_IDENTIFIER # 项目标识字符 VUE_APP_PROJECT_IDENTIFIER admin二引用路径变量 ${process…...
Vue中使用pdf.js实现在线预览pdf文件流
以下是在Vue中使用pdf.js实现在线预览pdf文件流的步骤: 1. 安装pdf.js npm install pdfjs-dist2. 引入pdf.js 在需要使用的组件中,使用以下代码引入pdf.js: import pdfjsLib from pdfjs-dist3. 加载pdf文件流 使用pdf.js的getDocument()方…...

态、势、感、知与时空、关系
态势感知是一种通过收集、整合、分析和解释大量的时空数据,以获取关于特定领域、地区或事件的全面理解的过程。时空和关系在态势感知中扮演着非常重要的角色。 态:态指的是物体或系统所处的状态或状况。在不同的态下,物体或系统的性质、行为和…...

D. Paths on the Tree
Problem - 1746D - Codeforces 思路:先分析一下题意,根据第一条性质,每次只能够从1开始,而第二条性质则表明对于每个节点来说,经过这个节点的子节点的路径条数应该尽量均衡,最大值与最小值相差不能超过1&am…...

CocosCreator3.8研究笔记(九)CocosCreator 场景资源的理解
相信很多朋友都想知道, Cocos Creator 资源的定义? Cocos Creator 常见的资源包含哪些?Cocos Creator 资源的管理机制是什么样的? Cocos Creator 中所有继承自 Asset 的类型都统称资源 ,例如:Texture2D、Sp…...

大数据课程L1——网站流量项目的概述整体架构
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解网站流量项目的案例概述; ⚪ 了解网站流量项目的数据埋点和采集; ⚪ 了解网站流量项目的整体架构; 一、网站流量项目概述 1. 背景说明 网站流量统计是改进网站服务的重要手段之一…...

提升数据库安全小技巧,使用SSH配合开源DBeaver工具连接数据库
title: 提升数据库安全小技巧,使用SSH配合开源DBeaver工具连接数据库 categories: 独立博客的方方面面 前段时间, 未来降低网址运行成本,搭了一套Mysql Docker 数据库, 包括外部链接,数据备份,数据导出,数据恢复一套解…...

信息安全技术概论-李剑-持续更新
图片和细节来源于 用户 xiejava1018 一.概述 随着计算机网络技术的发展,与时代的变化,计算机病毒也经历了从早期的破坏为主到勒索钱财敲诈经济为主,破坏方式也多种多样,由早期的破坏网络到破坏硬件设备等等 ,这也…...

java项目基于 SSM+JSP 的人事管理系统
java项目基于 SSMJSP 的人事管理系统 博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 大家好,今天和大家聊的是 Java 基于 SSM 的人事管理系统。…...

【Node.js】—基本知识点总结
【Node.js】—基本知识总结 一、命令行常用操作 二、Node.js注意点 Node.js中不能使用BOM和DOM操作 总结 三、Buffer buffer是一个类似于数组的对象,用于表示固定长度的字节序列buffer的本质是一段内存空间,专门用来处理二进制数据 特点:…...

Leetcode.174 地下城游戏
题目链接 Leetcode.174 地下城游戏 hard 题目描述 恶魔们抓住了公主并将她关在了地下城 d u n g e o n dungeon dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公…...

python实现adb辅助点击屏幕工具
#!/usr/bin/env python # -*- coding: utf-8 -*-import re import os import time import subprocess import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk# 设置ADB路径(根据你的系统和安装路径进行调整) ADB_PATH C…...

智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击
智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击 Safful发现了一个有趣的错误,有可能成为一些 DeFi 项目的攻击媒介。这个错误尤其与著名的 ERC777 代币标准有关。此外,它不仅仅是众所周知的黑客中常见的简单的重入问题。 这篇文章对 …...
nodejs 爬虫 axios 异步爬虫 教程 【一】
axios 自定义headers axios.defaults.headers.common["User-Agent"] "Googlebot/2.1 (http://www.google.com/bot.html)"; 运行环境: node :v18 const axios require("axios"); axios.defaults.headers.common["U…...
Swift学习笔记三(Dictionary 篇)
1 Dictionary 概念 字典储存无序的互相关联的同一类型的键和同一类型的值的集合。字典类型的全写方式 Dictionary<Key, Value>,简写方式 [Key: Value],建议使用简写方式。字典的 key 必须是可哈希的。 2 Dictionary创建 2.1 初始器创建方式 2.2 …...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...