Java Thread 线程安全问题 上锁 解锁

在这里插入图片描述

模拟问题

package com.zhong.thread.usethread;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @ClassName : ThreadProject
 * @Description : 线程安全问题小案例
 * @Author : zhx
 * @Date: 2024-02-19 13:21
 */
public class ThreadProject {
    public static void main(String[] args) {
        // 创建账户对象 代表共享账户
        Account acc = new Account("WPPZHX-999999999", 100);
        // 创建两个线程 代表两个用户 去同一个账户对象取钱 100
        new DrawThread(acc, "小王").start(); // 小王
        new DrawThread(acc, "小钟").start(); // 小钟
    }
}

class DrawThread extends Thread {
    private Account acc;

    public DrawThread(Account acc, String name) {
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        // 小王 小钟 各自取 100元
        acc.drawMoney(100);

    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Account {
    private String cardID;
    private double money;

    public void drawMoney(double getMoney) {
        // 获取当前取钱对象名字
        String name = Thread.currentThread().getName();
        if (this.money >= getMoney) {
            System.out.println(name + " 取钱 " + money);
            money -= getMoney;
            System.out.println(name + " 取钱后余额还剩 " + money);
        } else {
            System.out.println(name + " 取钱 余额不足......");
        }
    }
}

解决问题

在这里插入图片描述

在这里插入图片描述

  • synchronized() 快捷使用 选中要加锁的代码块 Ctrl + Alt + T 选择第 9 个
  • 静态方法使用锁的时候建议使用 Account.class 作为公共资源
package com.zhong.thread.usethread;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @ClassName : ThreadProject
 * @Description : 线程安全问题小案例
 * @Author : zhx
 * @Date: 2024-02-19 13:21
 */
public class ThreadProject {
    public static void main(String[] args) {
        // 创建账户对象 代表共享账户
        Account acc = new Account("WPPZHX-999999999", 100);
        // 创建两个线程 代表两个用户 去同一个账户对象取钱 100
        new DrawThread(acc, "小王").start(); // 小王
        new DrawThread(acc, "小钟").start(); // 小钟
    }
}

class DrawThread extends Thread {
    private Account acc;

    public DrawThread(Account acc, String name) {
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        // 小王 小钟 各自取 100 元
        acc.drawMoney(100);

    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Account {
    private String cardID;
    private double money;
    public static void  test() {
        // 静态方法使用锁的时候建议使用 Account.class 作为公共资源
        synchronized (Account.class){

        }
    }
    public void drawMoney(double getMoney) {
        // 获取当前取钱对象名字
        String name = Thread.currentThread().getName();
        synchronized (this) {
            if (this.money >= getMoney) {
                System.out.println(name + " 取钱 " + money);
                money -= getMoney;
                System.out.println(name + " 取钱后余额还剩 " + money);
            } else {
                System.out.println(name + " 取钱 余额不足......" + money);
            }
        }
    }
}

在这里插入图片描述

package com.zhong.thread.usethread;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @ClassName : ThreadProject
 * @Description : 线程安全问题小案例
 * @Author : zhx
 * @Date: 2024-02-19 13:21
 */
public class ThreadProject {
    public static void main(String[] args) {
        // 创建账户对象 代表共享账户
        Account acc = new Account("WPPZHX-999999999", 100);
        // 创建两个线程 代表两个用户 去同一个账户对象取钱 100
        new DrawThread(acc, "小王").start(); // 小王
        new DrawThread(acc, "小钟").start(); // 小钟
    }
}

class DrawThread extends Thread {
    private Account acc;

    public DrawThread(Account acc, String name) {
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        // 小王 小钟 各自取 100 元
        acc.drawMoney(100);

    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Account {
    private String cardID;
    private double money;

    public static void test() {
        // 静态方法使用锁的时候建议使用 Account.class 作为公共资源
        synchronized (Account.class) {

        }
    }
    // synchronized 直接给方法上锁
    public synchronized void drawMoney(double getMoney) {
        // 获取当前取钱对象名字
        String name = Thread.currentThread().getName();
        if (this.money >= getMoney) {
            System.out.println(name + " 取钱 " + money);
            money -= getMoney;
            System.out.println(name + " 取钱后余额还剩 " + money);
        } else {
            System.out.println(name + " 取钱 余额不足......" + money);
        }
    }
}

在这里插入图片描述

package com.zhong.thread.usethread;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName : ThreadProject
 * @Description : 线程安全问题小案例
 * @Author : zhx
 * @Date: 2024-02-19 13:21
 */
public class ThreadProject {
    public static void main(String[] args) {
        // 创建账户对象 代表共享账户
        Account acc = new Account("WPPZHX-999999999", 100);
        // 创建两个线程 代表两个用户 去同一个账户对象取钱 100
        new DrawThread(acc, "小王").start(); // 小王
        new DrawThread(acc, "小钟").start(); // 小钟
    }
}

class DrawThread extends Thread {
    private Account acc;

    public DrawThread(Account acc, String name) {
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        // 小王 小钟 各自取 100 元
        acc.drawMoney(100);

    }
}

@Data
@NoArgsConstructor
class Account {
    private String cardID;
    private double money;
    private final Lock lock =  new ReentrantLock();

    public Account(String cardID, double money) {
        this.cardID = cardID;
        this.money = money;
    }

    public static void test() {
        // 静态方法使用锁的时候建议使用 Account.class 作为公共资源
        synchronized (Account.class) {

        }
    }
    public  void drawMoney(double getMoney) {
        // 获取当前取钱对象名字
        String name = Thread.currentThread().getName();
        // 上锁
        lock.lock();
        try {   // 即使中间程序出错 也不影响锁
            if (this.money >= getMoney) {
                System.out.println(name + " 取钱 " + money);
                money -= getMoney;
                System.out.println(name + " 取钱后余额还剩 " + money);
            } else {
                System.out.println(name + " 取钱 余额不足......" + money);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 解锁
            lock.unlock();
        }

    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

postman也不行!IDEA接口调试插件

Postman是大家最常用的API调试工具,那么有没有一种方法可以不用手动写入接口到Postman,即可进行接口调试操作?今天给大家推荐一款IDEA插件:Apipost Helper,写完代码就可以调试接口并一键生成接口文档!而且还…

树和堆的精讲

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary_walk ⸝⋆ ━━━┓ - 个性标签 - :来于“云”的“羽球人”。…

MySQL的基础架构

文章目录 前言MySQL的基础架构总结 前言 你使用 MySQL 开发,你知道 MySQL 的基础架构吗?本文带你来入门MySQL 的基础架构 MySQL的基础架构 MySQL 是我们经常使用到的数据库。它的基础架构分为 server 层与存储引擎层。 server 层:用于存储…

nacos 2.3.1-SNAPSHOT 源码springboot方式启动(详细)附改造工程地址

文章时间是2024-2-18日,nacos默认develop分支,最新版是2.3.1-SNAPSHOT版本。 我们这里就以nacos最新版进行改造成springboot启动方式。 1. Clone 代码 nacos github地址:https://github.com/alibaba/nacos.git 根据上面git地址把源码克隆到…

oauth2 授权码模式 流程说明和接口整理

一、说明 oauth2 授权模式一共有四种,即隐式授权模式、授权码授权模式、密码授权模式和客户端授权模式。 这里仅对授权码授权模式所包含的流程和接口做说明和整理。 具体的概念和源码解读,资料有很多,可以自行去搜索学习。 二、流程说明 假…

OpenAI最新模型Sora到底有多强?眼见为实的真实世界即将成为过去!

文章目录 1. 写在前面2. 什么是Sora?3. Sora的技术原理 【作者主页】:吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作! 【作者推荐】:对JS逆向感…

maptalks多边形区域和点位-vue组件

多边形 <!-- 地图组件 --> <template><div :id="id" class="container"></div> </template><script> import _ from "lodash"; import "maptalks/dist/maptalks.css"; import * as maptalks from…

Open CASCADE学习|用点分割边

在Open CASCADE Technology&#xff08;OCCT&#xff09;中&#xff0c;几何模型是由拓扑&#xff08;Topology&#xff09;和几何&#xff08;Geometry&#xff09;两部分组成的。拓扑部分描述了形状的拓扑结构&#xff0c;比如边、面、体等&#xff0c;而几何部分则定义了这些…

金蝶云星空——用递归SQL查询物料分组

应用场景&#xff1a; 金蝶物料分组为树形结构&#xff0c;需要根据SQL查询同步到第三方系统中。 技术实现 用递归CTE按照树状结构展开物料分组 with cte as( select 0 as 物料分组层级,t1.FID,case when isnull(t1.FFULLPARENTID,) then .CAST(t1.FID AS VARCHAR(…

裸辞5个月,面试了37家公司,终于找到理想工作了

上半年裁员&#xff0c;下半年裸辞&#xff0c;有不少人高呼裸辞后躺平真的好快乐&#xff01;但也有很多人&#xff0c;裸辞后的生活五味杂陈。 面试37次终于找到心仪工作 因为工作压力大、领导PUA等各种原因&#xff0c;今年2月下旬我从一家互联网小厂裸辞&#xff0c;没想…

LeetCode JS专栏刷题笔记(二)

一、前言 LeetCode - JavaScript 专栏刷题笔记第二篇。 第一篇刷题笔记详见&#xff1a;LeetCode JS专栏刷题笔记&#xff08;一&#xff09; 二、算法题目 1. 复合函数 LeetCode地址&#xff1a;2629. 复合函数 请你编写一个函数&#xff0c;它接收一个函数数组 [f1, f2, …

(2024,自级联扩散,关键点引导的噪声重新调度,时间感知特征上采样器)进行廉价的扩展:用于更高分辨率适应的自级联扩散模型

Make a Cheap Scaling: A Self-Cascade Diffusion Model for Higher-Resolution Adaptation 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 2. 相关工作 4. 自级联扩散模型 …

【数据结构与算法】手搓JDK底层ArrayList底层 - 动态数组

数组 在介绍数组之前&#xff0c;我们先来看一段chatGPT给出的对于数组描述&#xff1a; 数组&#xff08;Array&#xff09;是一种线性数据结构&#xff0c;它由一组连续的内存空间组成&#xff0c;用来存储相同类型的数据元素。数组具有固定的大小&#xff0c;一旦创建后&a…

【Docker】前后端分离项目 Gin+Vue 容器化部署 | docker-compose 部署 | 部署 nginx 通过域名访问

文章目录 前言前后端不完全独立docker 部署mysqlredisrbac docker compose 部署部署 nginx 前后端独立部署 前言 项目地址&#xff1a;https://gitee.com/Cauchy_AQ/rbac 项目前端使用 vue3 并且由 vite 构建&#xff0c;后端采用 gin 框架&#xff0c;搭建了一个简易的权限管…

计算机设计大赛 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

WildCard:一个因太好用而被迫暂停服务的虚拟信用卡平台,魅力何在?

如果你需要使用Wildcard开通GPT4、Midjourney或是Only方式的话&#xff0c;请点击&#xff1a;WildCard使用教程 参考文章链接&#xff1a;WildCard&#xff1a;一个因太好用而被迫暂停服务的虚拟信用卡平台&#xff0c;魅力何在&#xff1f; 1、Wildcard用户数量激增&#x…

lombok的Getter, Setter报错 cannot find symbol

今天突然发现项目里的lombok失效了&#xff0c;get , set全部报错 java: cannot find symbol 觉得很奇怪&#xff0c;年前放假前都好好的&#xff0c;没改过代码&#xff0c;依赖&#xff0c;注解都正确&#xff0c;突然报这个错。 后来才发现是因为重装过系统&#xff0c;id…

机器人十大前沿技术(2023-2024年)

2023-2024年机器人十大前沿技术 1. 具身智能与垂直大模型 具身智能是指拥有自主感知、交互和行动能力的智能体&#xff0c;能够与环境进行实时互动&#xff0c;从而实现对环境的理解和适应。 “大模型”是指在深度学习和人工智能领域中&#xff0c;使用大量参数和数据进行训…

【Visual Studio】技巧 :自动与活动文档同步

在这里插入图片描述 工具 -> 选项 -> 项目和解决方案 - 勾选上面的 我厉害不&#xff01;&#xff01;&#xff01;

php基础学习之常用系统函数

一&#xff0c;有关输出的语句/函数 echo语句 用于输出一个或多个字符串 print语句 用于输出一个字符串&#xff08;用句点连接的多个字符串本质是一个字符串&#xff09;&#xff0c;与echo类似&#xff0c;但返回值为1 printf()函数 用于格式化输出字符串&#xff0c;类似于C…