多线程synchronized使用
来源:互联网 发布:阿玛迪斯战记 数据 编辑:程序博客网 时间:2024/06/06 20:32
多线程synchronized使用
概述
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。(摘自百度百科:https://baike.baidu.com/item/synchronized/8483356?fr=aladdin)
案例分析
- 需求说明:假设你的银行账户余额10000元。某日,你通过网上商城支付商品费用扣除费用100元,同时,你的朋友还款将向你的账户充值100元。这里涉及到一个多线程的问题,正常情况下,你的账户余额应该是10000元。
可能会出现的异常是:- 你向商家支付账款时,银行系统取出你的账户余额10000元,同时,你的朋友向你的账户发送了充值的请求,此时,向商家支付账款的请求还未结束,账户余额仍是10000元,所以,这时出现的结果是你的账户余额是10100元。
- 反过来讲,你的朋友先向你的账户发起了转账的申请,同时你也向商家账户发起了支付账款的请求,这时出现的情况可能是,账户余额在10000元的基础上先做了累加操作,同时又做了递减操作,那么你的余额便成9900元。
那么,如何解决这种情况呢?这就需要用到线程锁,即synchronized.
代码示例
- 创建账户余额类,并为结算方法做线程锁操作。
public class Account { private int balance = 10000; // 账户余额 public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } /** * 账户余额结算方法 * @param operationType 操作类型 * @param operationMoney 操作金额 * @return */ public synchronized int calc(String operationType, int operationMoney) { switch (operationType) { case "add": // 添加操作 this.balance += operationMoney; break; case "reduce": // 减少操作 this.balance -= operationMoney; break; default: break; } return this.balance; }}
- 创建测试类
public class SynchronizedDemo { public static void main(String[] args) { Account account = new Account(); System.out.println("账户初始余额:" + account.getBalance()); for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { int balance = account.calc("add", 100); System.out.println("当前线程:" + Thread.currentThread().getName() + "\t账户余额-添加操作:" + balance); } }, "addBalance-thread").start(); new Thread(new Runnable() { @Override public void run() { int balance = account.calc("reduce", 100); System.out.println("当前线程:" + Thread.currentThread().getName() + "\t账户余额-减少操作:" + balance); } }, "reduceBalance-thread").start(); } }}
在结算方法calc()
未加synchronized线程锁的时候,输出结果如下:
账户初始余额:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000当前线程:reduceBalance-thread 账户余额-减少操作:9900当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:addBalance-thread 账户余额-添加操作:10000当前线程:addBalance-thread 账户余额-添加操作:10200当前线程:reduceBalance-thread 账户余额-减少操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000当前线程:reduceBalance-thread 账户余额-减少操作:9900当前线程:addBalance-thread 账户余额-添加操作:10000
观察日志,发现在第三次和第四次操作时就出现了错误。账户余额多了100.
上述结果需要多运行几次,每次的结果不一致,但是会出现类似的错误的。
那么在calc()
加上线程锁后,运行日志如下:
第一次运行结果:
账户初始余额:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:addBalance-thread 账户余额-添加操作:10200当前线程:addBalance-thread 账户余额-添加操作:10300当前线程:reduceBalance-thread 账户余额-减少操作:10200当前线程:addBalance-thread 账户余额-添加操作:10300当前线程:addBalance-thread 账户余额-添加操作:10400当前线程:reduceBalance-thread 账户余额-减少操作:10300当前线程:reduceBalance-thread 账户余额-减少操作:10200当前线程:reduceBalance-thread 账户余额-减少操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000
第二次运行结果:
账户初始余额:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000当前线程:addBalance-thread 账户余额-添加操作:10100当前线程:reduceBalance-thread 账户余额-减少操作:10000
多次测试是没有问题的。
所以synchronized线程锁解决了这种多线程问题。
源代码:https://github.com/myNameIssls/javase-study/tree/master/javase-multithreading
阅读全文
0 0
- 多线程synchronized使用
- synchronized在多线程中的使用
- Synchronized在多线程中的使用
- Java多线程同步 synchronized使用
- 多线程 锁 synchronized 的使用
- Java多线程同步Synchronized使用分析
- Java多线程同步Synchronized使用分析
- Java多线程同步Synchronized使用分析
- Java多线程同步Synchronized使用分析
- Java中多线程Synchronized使用技巧
- java多线程中使用synchronized说明
- 【Java】多线程同步Synchronized使用分析
- Java 多线程中使用synchronized及解锁
- Java多线程同步Synchronized使用分析
- synchronized在多线程情况下的使用
- Java多线程同步 synchronized 关键字的使用
- Java多线程同步Synchronized使用分析
- 关于多线程中synchronized的使用位置
- CUDA学习六:图像的互操作性
- document.execCommand()的用法小记
- CUDA学习七:原子性
- 机器学习中的一些基本概念
- Java多线程的应用场景
- 多线程synchronized使用
- 第一次写博客。。。
- C进程的Memory Layout&linux进程的地址空间&函数调用过程
- 在APP中打开设备中安装的应用市场
- Tomcat同一目录下jar包加载顺序问题
- CUDA学习八:流
- Mysql主从配置,实现读写分离
- Visual Studio中VAssistX的使用学习笔记
- Java位运算