线程的同步:
由于同一进程的多个线程共享存储空间,在带来方便的同时也带来访问冲突的问题。例如在本例中若两个线程同时访问变量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("余额不足!"); } }
某次运行结果:
时间: 2024-10-25 09:59:04