本篇是多线程不安全实例,模拟的是两人取钱的过程,若两人同时取100,会造成余额为负的结果,说明多线程存在安全问题。
首先是不安全的实例。
package lesson04;
public class TestBank {
public static void main(String[] args) {
Account account = new Account("结婚基金", 100);
DrawingMoney you = new DrawingMoney(50,0,account);
DrawingMoney wife = new DrawingMoney(100,0,account);
new Thread(you).start();
new Thread(wife).start();
}
}
//账户
class Account {
String name;//卡名
int money;//卡内余额
//有参构造
public Account(String name,int money) {
this.name = name;
this.money = money;
}
}
//银行取钱,模拟多线程
class DrawingMoney implements Runnable {
int drawingMoney ;
int haveMoney;
Account account;
//构造器
public DrawingMoney(int drawingMoney, int haveMoney, Account account) {
this.drawingMoney = drawingMoney;
this.haveMoney = haveMoney;
this.account = account;
}
@Override
public void run() {
if (account.money - drawingMoney <= 0 ) {
System.out.println("卡里余额不足");
return;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money-drawingMoney;
haveMoney = haveMoney+drawingMoney;
System.out.println(Thread.currentThread().getName()+"手里有"+haveMoney);
System.out.println(account.name+"卡余额为"+account.money);
}
}
运行结果:
这里就引入了synchronized同步机制,使用锁加队列的方式确保了多线程操作的安全。这里包括两种:
1、synchronized方法:同步方法:public synchronized void method(args){};
2、synchronized方法体:synchronized(Obj){}
Obj称之为同步监视器,可以是任何对象,同步方法中无需指定同步监视器,因为同步方法的监视器就是this,这个对象的本身,或者是classl类
下面使用synchronized方法体对代码进行改造,使线程安全。
package lesson04;
public class TestBank {
public static void main(String[] args) {
Account account = new Account("结婚基金", 100);
DrawingMoney you = new DrawingMoney(50,0,account);
DrawingMoney wife = new DrawingMoney(100,0,account);
new Thread(you).start();
new Thread(wife).start();
}
}
//账户
class Account {
String name;//卡名
int money;//卡内余额
//有参构造
public Account(String name,int money) {
this.name = name;
this.money = money;
}
}
//银行取钱,模拟多线程
class DrawingMoney implements Runnable {
int drawingMoney ;
int haveMoney;
Account account;
//构造器
public DrawingMoney(int drawingMoney, int haveMoney, Account account) {
this.drawingMoney = drawingMoney;
this.haveMoney = haveMoney;
this.account = account;
}
//取钱
//synchronized默认锁的是this
@Override
public void run() {
//锁的对象就是变化的量,增删改的对象
synchronized (account){
if (account.money - drawingMoney <= 0 ) {
System.out.println("卡里余额不足");
return;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money-drawingMoney;
haveMoney = haveMoney+drawingMoney;
System.out.println(Thread.currentThread().getName()+"手里有"+haveMoney);
System.out.println(account.name+"卡余额为"+account.money);
}
}
}
运行结果: