在多个人对同一个程序进行访问时,可能会因为没有对该段程序进行并发处理,导致结果出现非预期结果
下面以一个存钱取钱的程序为例:(此处不考虑手续费!!)
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
如有问题请指出,谢谢。