线程的同步:
由于同一进程的多个线程共享存储空间,在带来方便的同时也带来访问冲突的问题。例如在本例中若两个线程同时访问变量balance,会造成结果不符合实际要求的情况,在本例中描述为:一个账号余额为1000元,两个或多个线程同时进行取款1000元操作,但取款操作后结果出现余额为负数,这与实际情况余额应该大于0元的结果不符。
在java中引入了“对象互斥锁”的概念来实现对不同线程的共享数据操作的同步。“对象互斥锁”不允许多个线程同时访问同一个条件变量(即共享数据)。实质上,是把多个线程对象并行的访问数据共享改为串行的访问数据,即同一时刻最多只有一个对象访问共享数据。
java中针对方法提出一套机制,就是synchronized关键字,它包括两种用法:synchronized修饰方法和synchronized修饰程序块。
本例中定义了3个类:
Bank(定义银行账号),Operation(线程类,实现存/取款操作)和TestBankOperation(主类)
本例中实现线程同步的方法:
1)给public void deposite(double dmount)和 public void withdrawal(double dmount)方法加锁,
即加上关键字 synchronized
2)在取款和存款的过程中给bank对象加锁
public class TestBankOperation {
public static void main(String[] args) {
// TODO Auto-generated method stub
Bank bank = new Bank("1002",1000);
//创建线程的方法一:继承Thread类
new Operation(1+"# ",bank,1000).start();
new Operation(0+"# ",bank,1000).start();
new Operation(3+"# ",bank,1000).start();
/*
//创建线程的方法二:实现Runnable接口
Operation o = new Operation("#",bank,1000);
Thread t1 = new Thread(o);
Thread t2 = new Thread(o);
Thread t3 = new Thread(o);
t1.start();
t2.start();
t3.start();
*/
}
}
/*
*线程类,实现了同步取款操作
*/
class Operation extends Thread
//class Operation implements Runnable
{
Bank bank;
double mount;
String name;
public Operation(String name)
{
super(name);
//this.name = name;
}
public Operation(String name,Bank bank,double dmount)
{
super(name);
//this.name = name;
this.bank = bank;
this.mount = dmount;
}
/*
public void run()
{
//bank.deposite(mount);
bank.withdrawal(mount);
}
*/
public void run()
{
synchronized(bank)
{
bank.withdrawal(mount);
}
}
}
/*
* 银行账号类
*/
class Bank
{
String account;//账号
double balance;//余额
Bank(String account,double balance)
{
this.setAccount(account);
this.balance = balance;
}
//设置账号
public void setAccount(String account)
{
this.account = account;
}
//设置余额
public void setBalance(double balance)
{
this.balance = balance;
}
//获取账号
public String getAccount()
{
return this.account;
}
//获取余额
public double getBanlance()
{
return this.balance;
}
/*
* 存款
* @param dmount存款金额
*/
public void deposite(double dmount)
//public synchronized void deposite(double dmount)
{
this.setBalance(this.getBanlance()+dmount);
System.out.println(Thread.currentThread().getName()+"线程存款成功! "+"存款为:" + dmount + " 当前余额为:" + this.balance+"\n");
}
/*
* 取款操作
* @param dmount 取款金额
*/
public void withdrawal(double dmount)
//public synchronized void withdrawal(double dmount)
{
if(dmount <= this.balance)
{
System.out.println(Thread.currentThread().getName()+"线程取款成功! "+"吐出钞票为:" + dmount);
this.setBalance(this.balance-dmount);
System.out.println("当前余额为:" + this.balance+"\n");
}
else
System.out.println("余额不足!");
}
}
某次运行结果: