当前位置: 首页 > 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 …...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...