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

【多线程】线程安全与线程同步

线程安全与线程同步

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 << "绝密指令为&#xff1a;";cout << SecretPointer << endl; }void Change(int& number, int* const FixedPointer) {cout << "更换站台数字为&#xff1a;";c…...

Unity——脚本与序列化

在介绍序列化之前&#xff0c;我们先来了解一下为什么要对数据进行序列化 数据序列化有以下几个主要的应用场景和目的&#xff1a; 1. 持久化存储&#xff1a;序列化可以将对象或数据结构转换为字节序列&#xff0c;使得其可以被存储在磁盘上或数据库中。通过序列化&#xff…...

NJ求职盘点

电子显示 集成电路 地平线 后摩智能 芯启源 自动驾驶 地平线 栖霞区兴智科技园 泊车、SLAM/3D算法工程师 https://wecruit.hotjob.cn/SU64819a4f2f9d2433ba8b043a/pb/social.html?currentPage1 后摩智能 栖霞区兴智科技园 视觉感知算法资深工程师 可以做自动驾驶前瞻性…...

01卡特兰数

卡特兰数跟排列组合很有关系&#xff0c;所以在看此文章前请掌握&#xff1a; 加法原理乘法原理A(m,n)计算公式及其原理C(m,n)计算公式及其原理 前言 今天您将会学习到基本的卡特兰数及其应用。 一、卡特兰数是什么&#xff1f; 卡特兰数&#xff08;Catalan number&#xff0…...

若依前端vue设置子路径

若依前端vue设置子路径 说明&#xff1a;本文档中以前后端分离版为例&#xff0c;版本为: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文件流的步骤&#xff1a; 1. 安装pdf.js npm install pdfjs-dist2. 引入pdf.js 在需要使用的组件中&#xff0c;使用以下代码引入pdf.js&#xff1a; import pdfjsLib from pdfjs-dist3. 加载pdf文件流 使用pdf.js的getDocument()方…...

态、势、感、知与时空、关系

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

D. Paths on the Tree

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

CocosCreator3.8研究笔记(九)CocosCreator 场景资源的理解

相信很多朋友都想知道&#xff0c; Cocos Creator 资源的定义&#xff1f; Cocos Creator 常见的资源包含哪些&#xff1f;Cocos Creator 资源的管理机制是什么样的&#xff1f; Cocos Creator 中所有继承自 Asset 的类型都统称资源 &#xff0c;例如&#xff1a;Texture2D、Sp…...

大数据课程L1——网站流量项目的概述整体架构

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

提升数据库安全小技巧,使用SSH配合开源DBeaver工具连接数据库

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

信息安全技术概论-李剑-持续更新

图片和细节来源于 用户 xiejava1018 一.概述 随着计算机网络技术的发展&#xff0c;与时代的变化&#xff0c;计算机病毒也经历了从早期的破坏为主到勒索钱财敲诈经济为主&#xff0c;破坏方式也多种多样&#xff0c;由早期的破坏网络到破坏硬件设备等等 &#xff0c;这也…...

java项目基于 SSM+JSP 的人事管理系统

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

【Node.js】—基本知识点总结

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

Leetcode.174 地下城游戏

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

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路径&#xff08;根据你的系统和安装路径进行调整&#xff09; ADB_PATH C…...

智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击

智能合约安全分析&#xff0c;针对 ERC777 任意调用合约 Hook 攻击 Safful发现了一个有趣的错误&#xff0c;有可能成为一些 DeFi 项目的攻击媒介。这个错误尤其与著名的 ERC777 代币标准有关。此外&#xff0c;它不仅仅是众所周知的黑客中常见的简单的重入问题。 这篇文章对 …...

nodejs 爬虫 axios 异步爬虫 教程 【一】

axios 自定义headers axios.defaults.headers.common["User-Agent"] "Googlebot/2.1 (http://www.google.com/bot.html)"; 运行环境&#xff1a; node &#xff1a;v18 const axios require("axios"); axios.defaults.headers.common["U…...

Swift学习笔记三(Dictionary 篇)

1 Dictionary 概念 字典储存无序的互相关联的同一类型的键和同一类型的值的集合。字典类型的全写方式 Dictionary<Key, Value>&#xff0c;简写方式 [Key: Value]&#xff0c;建议使用简写方式。字典的 key 必须是可哈希的。 2 Dictionary创建 2.1 初始器创建方式 2.2 …...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;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 …...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...