在多个人对同一个程序进行访问时,可能会因为没有对该段程序进行并发处理,导致结果出现非预期结果
下面以一个存钱取钱的程序为例:(此处不考虑手续费!!)
package com.robert.bean; public class BankAccount { private int cardMoney = 1000; private int cashMoney = 1000; //存款 public void deposit(int number) { cashMoney = cashMoney - number; System.out.println("存款: 当前现金为:"+cashMoney+"$"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cardMoney = cardMoney + number; System.out.println("存款:当前卡上金额为:"+cardMoney+"$"); } //取款 public void withdrawl(int number) { cashMoney = cashMoney + number; System.out.println("取款: 当前现金为:"+cardMoney+"$"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cardMoney = cardMoney - number; System.out.println("取款: 当前卡上金额为:"+cashMoney+"$"); } public int getAmount() { return cardMoney + cashMoney; } }
package com.robert.test; import com.robert.bean.BankAccount; public class TestSynchronized implements Runnable { BankAccount bankAccount = new BankAccount(); public static void main(String[] args) { TestSynchronized testSync = new TestSynchronized(); Thread thread1 = new Thread(testSync); Thread thread2 = new Thread(testSync); thread1.start(); thread2.start(); } public void run() { for(int i=0;i<20;i++) { bankAccount.deposit(50); bankAccount.withdrawl(40); } System.out.println("总金额为:"+bankAccount.getAmount()); } }卡上有1000元,手上有1000元现金
现在进行存钱取钱操作,理论上不管怎么操作 卡上的钱+现金=2000
但是运行该程序你会发现,会有总金额不是2000的结果
显然说明该程序有误!
而通过给方法加关键字synchronized就能解决这个小问题。
修改后的程序如下所示
package com.robert.bean; public class BankAccount { private int cardMoney = 1000; private int cashMoney = 1000; //存款 public synchronized void deposit(int number) { cashMoney = cashMoney - number; System.out.println("存款: 当前现金为:"+cashMoney+"$"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cardMoney = cardMoney + number; System.out.println("存款:当前卡上金额为:"+cardMoney+"$"); } //取款 public synchronized void withdrawl(int number) { cashMoney = cashMoney + number; System.out.println("取款: 当前现金为:"+cardMoney+"$"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cardMoney = cardMoney - number; System.out.println("取款: 当前卡上金额为:"+cashMoney+"$"); } public synchronized int getAmount() { return cardMoney + cashMoney; } }
在此通过这个小例子对该关键字进行简单的介绍:
在java中synchronized有两种方法:
1 synchronized方法
2 synchronized声明
对于加过synchronized关键字的方法会产生两种影响
(1) 当一个线程正在执行一个synchronized的方法时,对于同一对象的调用该方法的其他线程将会被阻塞,直到第一个线程执行完毕。
(2)当一个synchronized的方法存在时,那么该方法就会同调用该方法的对象的其他调用之间建立happens-before关系,以使其他的线程对当前对象可见。
转载
原文出自:http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
如有问题请指出,谢谢。