多线程同步---synchronize
2016-06-14 21:49
267 查看
在项目中我们经常遇到这样一种情况:两个人同时操作数据库,导致数据异常。针对于数据库级别我们采用锁机制,还有一种方法使规定我们方法调用的权限,当你在使用这个资源的时候别人是不允许使用的,在多线程中只需要一个修饰词就可以实现:synchronize。
第一步: 下面我们采用银行取钱的场景来代码实现
Account类:
线程类:
client进行测试:
多次执行出现的结果:
![](https://img-blog.csdn.net/20160614214518576)
![](https://img-blog.csdn.net/20160614214524908)
第二步:我们给我们需要执行的逻辑加上synchronize
run方法下面的synchronized(account)解开注释继续执行,查看结果。
多次执行结果只有:
![](https://img-blog.csdn.net/20160614214533201)
解析:当我们加上synchronize修饰词的时候相当于把account类给锁住了,本线程使用account的时候,其他线程不能对account进行编辑。
第三步:给Account加一个有 synchronize修饰的draw方法,即将代码中的draw注释解除,drawThread方法中也需要改变:
![](https://img-blog.csdn.net/20160614214539358)
总结:
关于同步方法修饰词synchronize的使用我们分三步来走,第一步,不加修饰词,多次执行会发现偶尔出现错误。第二步,当给Accout实体加入synchronize修饰词后发现多次执行也不会发生错误。第三步,给Account实体加一个有synchronize修饰的draw方法,大家会发现这样虽然效果和第二步是一直的,但是在灵活性上明显是第三步的修改要好很多。
第一步: 下面我们采用银行取钱的场景来代码实现
Account类:
public class Account { private String accountNo; 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; } private double balance; public Account(){ } public Account(String accountNo,double balance){ this.accountNo=accountNo; this.balance=balance; } public int hashCode(){ return accountNo.hashCode(); } public boolean equals(Object obj){ if(obj !=null && obj.getClass()==Account.class){ Account target =(Account)obj; return target.getAccountNo().equals(accountNo); } return false; } /*public synchronized void draw(double drawAmount){ if(balance >=drawAmount){ System.out.println(Thread.currentThread().getName()+"取钱成功,吐出钞票"+drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } balance-=drawAmount; System.out.println("\t余额为:"+balance); }else{ System.out.println(Thread.currentThread().getName()+"取钱失败!余额不足!"); } } */ }
线程类:
public class DrawThread extends Thread{ private Account account; private double drawAmount; public double getDrawAmount() { return drawAmount; } public void setDrawAmount(double drawAmount) { this.drawAmount = drawAmount; } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } public DrawThread(String name, Account account, double drawAmount){ super(name); this.account=account; this.drawAmount=drawAmount; } public void run(){ // synchronized(account){ if(account.getBalance() >=drawAmount){ System.out.println(getName()+"取钱成功,吐出钞票"+drawAmount); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } account.setBalance(account.getBalance()-drawAmount); System.out.println("\t余额为:"+account.getBalance()); }else{ System.out.println(getName()+"取钱失败!余额不足!"); } } /*account.draw(drawAmount);*/ // } }
client进行测试:
public class TestDraw { public static void main(String[] args) { Account acct= new Account("1234567",1000); new DrawThread("甲",acct,800).start(); new DrawThread("乙",acct,800).start(); } }
多次执行出现的结果:
第二步:我们给我们需要执行的逻辑加上synchronize
run方法下面的synchronized(account)解开注释继续执行,查看结果。
多次执行结果只有:
解析:当我们加上synchronize修饰词的时候相当于把account类给锁住了,本线程使用account的时候,其他线程不能对account进行编辑。
第三步:给Account加一个有 synchronize修饰的draw方法,即将代码中的draw注释解除,drawThread方法中也需要改变:
public synchronized void draw(double drawAmount){ if(balance >=drawAmount){ System.out.println(Thread.currentThread().getName()+"取钱成功,吐出钞票"+drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } balance-=drawAmount; System.out.println("\t余额为:"+balance); }else{ System.out.println(Thread.currentThread().getName()+"取钱失败!余额不足!"); } }DrawThread中的run方法:
public void run(){ account.draw(drawAmount); }执行结果:
总结:
关于同步方法修饰词synchronize的使用我们分三步来走,第一步,不加修饰词,多次执行会发现偶尔出现错误。第二步,当给Accout实体加入synchronize修饰词后发现多次执行也不会发生错误。第三步,给Account实体加一个有synchronize修饰的draw方法,大家会发现这样虽然效果和第二步是一直的,但是在灵活性上明显是第三步的修改要好很多。
相关文章推荐
- 利用Wireshark 解密HTTPS流量
- 基于KNN的手写数字识别
- swift中如何写π
- 支付SDK
- CentOs 6.5 安装OpenSSL
- 使物体按照指定路径移动
- swift统一设置导航条按钮属性
- 笔记
- hjr-Eclipse与MyEclipse乱码问题解决
- C++ 智能指针详解
- jdbc代码
- RESTFul Shiro
- swift添加导航条按钮,不生效的原因
- Qt设置标题栏图标、文字和标题栏样式的方法
- swift设置导航条左边的按钮
- 闲话数据库(二)---第三范式/BCNF
- android studio导入第三方工具
- Input.GetMouseButton 获取鼠标按钮
- 自动化配置ssh连接
- swift可以直接修改控件的frame