关于线程安全问题有一个经典的例子就是----银行取钱问题
- 用户输入账号密码,系统匹配账号密码是否正确
- 用户输入取款金额
- 系统判断账号余额是否大于取款金额
- 如果余额大于取款金额则取款成功,反正取款失败
package com.synchronized1; public class Account { //账号ID private String accountNo; //余额 private double balance; public Account(String accountNo, double balance) { super(); this.accountNo = accountNo; this.balance = balance; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } }
package com.synchronized1; public class DrawMoney implements Runnable { private Account account; private double drawAmount; private String name; public DrawMoney(String name,Account account,double drawAmount) { this.name = name; this.account = account; this.drawAmount = drawAmount; } @Override public void run() { if(account.getBalance()>drawAmount){ System.out.println(name+"取钱成功,吐出钞票:"+drawAmount); account.setBalance(account.getBalance()-drawAmount); System.out.println("余额:"+account.getBalance()); }else{ System.out.println("取钱失败,余额不足!"); } } }
package com.synchronized1; public class DrawMain { public static void main(String[] args) { Account ac=new Account("111", 1000); new Thread(new DrawMoney("甲", ac, 800)).start(); new Thread(new DrawMoney("乙", ac, 800)).start(); } }
问题出现了:账户余额只有1000的时候取出了1600
乙取钱成功,吐出钞票:800.0 甲取钱成功,吐出钞票:800.0 余额:200.0 余额:-600.0
采用synchronized保证线程安全:
package com.synchronized2; public class DrawMoney implements Runnable { private Account account; private double drawAmount; private String name; public DrawMoney(String name,Account account,double drawAmount) { this.name = name; this.account = account; this.drawAmount = drawAmount; } @Override public void run() { //使用account作为同步监视器,任何线程进入下面的同步代码块之前必须先 //获得account账户的锁定 synchronized(account){ if(account.getBalance()>drawAmount){ System.out.println(name+"取钱成功,吐出钞票:"+drawAmount); account.setBalance(account.getBalance()-drawAmount); System.out.println("余额:"+account.getBalance()); }else{ System.out.println("取钱失败,余额不足!"); } } } }
甲取钱成功,吐出钞票:800.0 余额:200.0 取钱失败,余额不足!
更好的设计方式:
package com.synchronized3; public class Account{ //账号ID private String accountNo; //余额 private double balance; public Account(String accountNo, double balance) { super(); this.accountNo = accountNo; this.balance = balance; } public synchronized void draw(double drawAmount){ if(balance>=drawAmount){ System.out.println(Thread.currentThread().getName()+" 取钱成功,吐出钞票:"+drawAmount); balance-=drawAmount; System.out.println("余额:"+(balance-drawAmount)); }else{ System.out.println("取钱失败,余额不足!"); } } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public double getBalance() { return balance; } }
package com.synchronized3; public class DrawMoney implements Runnable { private Account account; private double drawAmount; public DrawMoney(Account account,double drawAmount) { this.account = account; this.drawAmount = drawAmount; } @Override public void run() { //同步方法的同步不监视器是this,this代表draw方法的对象(Account对象) account.draw(drawAmount); } }
package com.synchronized3; public class DrawMain { public static void main(String[] args) { Account ac=new Account("111", 1000); new Thread(new DrawMoney( ac, 800)).start(); new Thread(new DrawMoney(ac, 800)).start(); } }
Thread-0 取钱成功,吐出钞票:800.0 余额:-600.0 取钱失败,余额不足!
相关推荐
MFC 多线程及线程同步 MFC 多线程及线程同步 MFC 多线程及线程同步
java线程同步java线程同步java线程同步
线程同步线程同步线程同步线程同步线程同步C#代码
d: 经典线程同步互斥问题 e: 使用关键段解决子线程互斥问题 f: 利用事件实现线程同步问题 g: 利用互斥量来解决线程同步互斥问题 h: problem1 生产者消费者问题 (1生产者 1消费者 1缓冲区) problem1 more ...
C#线程同步的几种方法 C#线程同步的几种方法
1.使用三种VC的多线程同步方法编写一个多线程的程序(要求在屏幕上先显示Hello,再显示World)。 1)基于全局变量的多线程同步程序; 2)基于事件的多线程同步程序; 3)基于临界区的多线程同步程序。
介绍了linux线程同步的所有方式,包括互斥、自旋、信号量、条件变量等技术
.NET多线程同步方法详解(一):自由锁(InterLocked) 本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再赘述了。直接接入主题,在多线程开发的应用中,线程同步是不可避免的。在.Net框架中,...
简单学习用例,利用线程锁对线程同步进行控制,保证对公共资源的访问不出现错误!
同时其它线程为保证数据一致性,不能调用该功能。 举例1: 银行存款 5000。柜台,折:取3000;提款机,卡:取 3000。剩余:2000 举例2: 内存中100字节,线程T1欲填入全1, 线程T2欲填入全0。但如果T1执行了50个字节...
多线程中的同步问题的几种解决方案,新手可以看看。主要通过临界区线程同步,互斥内核对象、事件内核对象,信号量内核对象来实现线程同步问题。
C# 线程同步.rarC# 线程同步.rarC# 线程同步.rarC# 线程同步.rarC# 线程同步.rar
线程同步的四种方法的代码。事件 互斥量 信号量 临界区
本文件为操作系统中的线程同步实验的实验报告,有详细的代码和解释。
利用 CountDownLatch 类实现线程同步,而不用回调机制。详见我的博文 http://blog.csdn.net/kroclin/article/details/37956949
本工程中包含了线程同步的五种方法,现在拿出来和大家一起分享,VC6.0编译测试通过,工程中包含了5个小工程,具体讲述每种线程同步方法的具体使用列子,而且有详细的注释。
很不错的Delphi多线程和线程同步的例子,完整源码 原来的一个不知道CSDN怎么把文件搞丢了!新传一个资源,包含一个线程排序的例子!代码均搜集自网上!
很不错的源码,3种多线程实现同步方法
本实例写了一个多线程,从中您可以学到线程创建,线程同步,等基本知识。
通过模拟公交车运行时,司机,售票员以及乘客之间的同步状态来实现线程同步