因为线程在执行的过程中具有一定的不确定性,在并发的时候就会出现安全问题,因此一般需要采取一定的措施来保证线程的安全,同步代码块就是其中一种方式。
以下是模拟银行取钱的多线程小例子,两个都能确保安全,但是有一种却更好一些。
例1:
packagedemo1;
/**
*
模拟两个人同时取一个账户的钱,必须只能有一个人能取成功
*@authortuzongxun
*
*/
publicclass ThreadTest6 {
publicstaticvoidmain(String[]args)
{
// 创建一个用户账户
Account account = newAccount("tu", 1000);
// 创建两个线程模拟取钱
GetMoney get1 = newGetMoney("甲", account,
600);
GetMoney get2 = newGetMoney("乙", account,
500);
// 启动线程
get1.start();
get2.start();
}
}
/**
* 模拟账户
* @authortuzongxun
*
*/
class Account {
/**
* 账户名
*/
private StringaccountNum;
/**
* 账户余额
*/
private Doublemoney;
publicAccount(String accountNum,double money) {
this.accountNum = accountNum;
this.money = money;
}
public StringgetAccountNum() {
returnaccountNum;
}
publicvoidsetAccountNum(StringaccountNum) {
this.accountNum = accountNum;
}
public DoublegetMoney() {
returnmoney;
}
publicvoidsetMoney(Double money) {
this.money = money;
}
}
classGetMoneyextends
Thread {
privatefinaldoublenum;
privatefinal Accountaccount;
publicGetMoney(String name,Account account,double num) {
super(name);
this.num = num;
this.account = account;
}
@Override
publicvoidrun() {
/**
* 这里锁住了整个用户对象,所以先开始的线程会锁定对象,另一个不能获得对象,无法结束
* 只有当操作账户的线程结束后,另一个线程才能结束
*/
synchronized (account) {
if (account.getMoney() >num) {
account.setMoney(account.getMoney() -num);
System.out.println("用户(
" + this.getName()
+ " )取钱成功,取了("
+ account.getAccountNum()
+ ")的账户:" +num
+ "元");
System.out.println("账户余额:"
+ account.getMoney() +"元");
}else {
System.out.println("用户(
" + this.getName()
+ " )取钱失败");
System.out.println("账户余额:"
+ account.getMoney() +"元");
}
}
}
}
例2:
packagedemo1;
/**
* 模拟两个人同时取一个账户的钱,必须只能有一个人能取成功
* @authortuzongxun
*
*/
publicclass ThreadTest7 {
publicstaticvoidmain(String[]
args) {
Account1 account = newAccount1("tu", 1000);
newGetMoney1("甲", account, 600).start();
newGetMoney1("乙", account, 500).start();
}
}
/**
* 模拟账户
* @authortuzongxun
*
*/
class Account1 {
private StringaccountName;
privatedoublebalance;
publicAccount1(StringaccountName,double balance) {
this.accountName = accountName;
this.balance = balance;
}
public StringgetAccountName() {
returnaccountName;
}
publicvoidsetAccountName(StringaccountName) {
this.accountName = accountName;
}
publicdoublegetBalance() {
returnbalance;
}
publicvoidsetBalance(double balance) {
this.balance = balance;
}
/**
* 这里只是锁住了取钱的方法,所以有可能第一个线程运行一半时,第二个开始运行并可能先结束
*但是就算第一个后结束,第二个线程依然取钱失败。
*@param money
* @return
*/
publicsynchronizeddoublegetMondy(double
money) {
if (balance > money) {
balance -= money;
return 1;
} else {
return -1;
}
}
};
classGetMoney1extends
Thread {
privatefinal Account1account;
privatefinaldoublemoney;
publicGetMoney1(String name,Account1 account,double money) {
super(name);
this.account = account;
this.money = money;
}
@Override
publicvoidrun() {
double getMoney =account.getMondy(money);
if (getMoney > 0){
System.out.println(this.getName()
+ "取款成功,取了"
+ account.getAccountName() +"账户:"
+ money
+ "元");
System.out.println("账户余额:"
+ account.getBalance());
} else {
System.out.println(this.getName()
+ "取款失败");
System.out.println("账户余额:"
+ account.getBalance());
}
}
}