银行取款[多线程]{未进行线程同步}(junit不适合多线程并发单元测试)
2023-09-14 09:04:40 时间
由于计算机多任务、多进程、多线程的支持,使得计算机资源的服务效率提高,服务器对请求的也使用线程来相应,所有,代码中涉及到同时对共享数据的操作,将在
多线程环境中操作数据,导致数据安全问题。
经典例子:老婆(朱丽叶)老公(罗密欧),使用银行卡和存折,或者网银等,同时对同一账户操作的安全问题。
如果要保证多线程下数据安全,就要实现线程同步(例如:一
Gradle从0入门到实战系列【八】SpringBoot集成Junit单元测试 JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
Java程序员必须要知道的单元测试框架Junit详解 作为一名java开发者,相信你或多或少的接触过单元测试,对于测试来讲它是一门能够区分专业开发人员与业余开发人员的重要学科,这篇文章将对java中最常见的一个单元测试框架junit进行一个梳理和讲解。如果你之前没接触过,那么就通过这篇文章进行一个学习。如果你是一个测试老手,我也希望这篇文章能够加深你的印象。
由于计算机多任务、多进程、多线程的支持,使得计算机资源的服务效率提高,服务器对请求的也使用线程来相应,所有,代码中涉及到同时对共享数据的操作,将在
多线程环境中操作数据,导致数据安全问题。
经典例子:老婆(朱丽叶)老公(罗密欧),使用银行卡和存折,或者网银等,同时对同一账户操作的安全问题。
如果要保证多线程下数据安全,就要实现线程同步(例如:一间小厕所,就得有一个锁,保证同一时间为一个人服务)。其他文章讲:
此处用多线程实现,同时取款的模拟实现,未进行线程同步操作,查看取款安全隐患问题,代码如下:
银行账户:
package com.tsxs.bank; public class BankAccount { //余额 private int balance = 500; //查询 public int getBalance(){ return banlance; //取款 public void withdraw(int amount){ banlance = banlance - amount; //存款 public void deposit(int amount){ banlance = banlance + amount;
线程类:
package com.tsxs.syncmethods; import com.tsxs.bank.BankAccount; * 此线程类实现Runnable接口 * 未进行线程同步 * */ public class NoSync implements Runnable{ //所有Thread多线程线程都共享Runnable(接口对象)和account对象 private BankAccount account = new BankAccount(); @Override public void run() { for(int i = 0; i i++){ //总共取款5次 makeWithdraw(100); //每次取款100 if(account.getBalance() 0){ System.out.println(""+Thread.currentThread().getName()+" 透支了!"); * makeWithdraw 账户取款 * @param amount 取款金额 br / * 打印log记录取款过程 * */ private void makeWithdraw(int amount){ if(account.getBalance() = amount){ //如果余额足够则取款 System.out.println(""+Thread.currentThread().getName()+" 准备取款!"); try { Thread.sleep(500); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName()+" 准备取款,等待0.5s线程中断!"+e.getMessage()); account.withdraw(amount); System.out.println(""+Thread.currentThread().getName()+" 完成"+amount+"取款!余额为"+account.getBalance()); }else{ //余额不足则提示 System.out.println(""+"余额不足以支付"+Thread.currentThread().getName()+amount+" 的取款,余额为"+account.getBalance());
测试代码:
package com.tsxs.test; import org.junit.Test; import com.tsxs.syncmethods.NoSync; public class TreadSyncTest { // @Test // public void test() { /*Junit不适合多线程并发测试。 因为线程还在激活状态的时候,Junit已经执行完成。 在Junit的TestRunner中,它没有被设计成搜寻Runnable实例, 并且等待这些线程发出报告,它只是执行它们并且忽略了它们的存在。 综上,不可能在Junit中编写和维护多线程的单元测试。 public static void main(String[] args) { //实现Runnable:所有Thread多线程线程都共享Runnable(接口对象) NoSync target =new NoSync(); //创建李琦和他老婆两个线程实现取款(同时) Thread lq = new Thread(target); lq.setName("罗密欧"); Thread lqwf = new Thread(target); lqwf.setName("朱丽叶"); //调用Thread对象的start()方法,启动线程,执行run()方法(OS) lq.start(); lqwf.start();
打印log记录为:
朱丽叶 准备取款! 罗密欧 准备取款! 朱丽叶 完成100取款!余额为400 罗密欧 完成100取款!余额为400 罗密欧 准备取款! 朱丽叶 准备取款! 朱丽叶 完成100取款!余额为200 罗密欧 完成100取款!余额为200 朱丽叶 准备取款! 罗密欧 准备取款! 朱丽叶 完成100取款!余额为100 罗密欧 完成100取款!余额为100 朱丽叶 准备取款! 罗密欧 准备取款! 罗密欧 完成100取款!余额为-100 朱丽叶 完成100取款!余额为-100 朱丽叶 透支了! 余额不足以支付朱丽叶100 的取款,余额为-100 朱丽叶 透支了! 罗密欧 透支了! 余额不足以支付罗密欧100 的取款,余额为-100 罗密欧 透支了!
分析结果,可见:
双线程总共取款10次,账户总额为500.
取款结果:取款成功600元,余额显示不对,最终账户余额为-100,已透支。
现实中,此取款代码是有严重bug的,上边数据对于银行是危险的,个人也会带来不必要的麻烦。
Gradle从0入门到实战系列【八】SpringBoot集成Junit单元测试 JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
Java程序员必须要知道的单元测试框架Junit详解 作为一名java开发者,相信你或多或少的接触过单元测试,对于测试来讲它是一门能够区分专业开发人员与业余开发人员的重要学科,这篇文章将对java中最常见的一个单元测试框架junit进行一个梳理和讲解。如果你之前没接触过,那么就通过这篇文章进行一个学习。如果你是一个测试老手,我也希望这篇文章能够加深你的印象。
相关文章
- Java1.6多线程之同步方法
- 5天不再惧怕多线程——第四天 信号量
- java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)
- 多线程爬虫链家基本信息
- java多线程(二)——锁机制synchronized(同步方法)
- C#使用Monitor类、Lock和Mutex类进行多线程同步
- C# 多线程参数传递
- Groovy里使用Runnable实现多线程
- 【Python成长之路】python并发学习:多进程与多线程的用法及场景介绍
- C++多线程编程:同步之互斥量Mutex
- C/C++ 实现多线程与线程同步
- Java学习路线-15:多线程的同步与死锁
- 为多线程处理同步数据(包括实例和静态成员)
- 010-多线程-JUC集合-Queue-ConcurrentLinkedQueue
- 003-多线程-锁-JUC锁-Lock及ReentrantLock、公平锁、非公平锁
- 002-多线程-锁-同步锁-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现
- 001-多线程-JUC线程池-线程池架构-Executor、ExecutorService、ThreadPoolExecutor、Executors
- .net多线程,线程异步,线程同步,并发问题---1---ShinePans
- android NDK编程:使用posix多线程与mutex相互排斥同步
- 多线程第四篇秒杀 一个经典的多线程同步问题
- 多线程有几种实现方法,都是什么?同步的方法有几种,都是什么?
- JAVA在语言级支持多线程
- 多线程间的同步
- 多线程同步AutoResetEvent 和ManualResetEvent
- 干货~多线程下1分钟完成1000万条数据插入到数据库中
- java 线程安全的原因_java的多线程:java安全问题产生的原因与JMM的关系