Ari*_*deh 1 java multithreading thread-safety
我有一种方法,它接收两个银行帐户作为输入并交换它们的值:
Public void TransferAccount(AccountID id1, AccountID id2){
Account a1 = id1.GetAccount();
Account a2 = id2.GetAccount();
//Swap amounts.
Temp = a1.Balance;
a1.Balance = a2.Balance;
a2.Balance = Temp;
}
Run Code Online (Sandbox Code Playgroud)
我想让这个方法具有最高性能的线程安全(我想这意味着我们可能不会使方法同步),我们也要小心死锁,
我想到了以下解决方案:
Public void TransferAccount(AccountID id1, AccountID id2){
Account a1 = id1.GetAccount();
Account a2 = id2.GetAccount();
//Swap amounts.
synchronized(a1){
wait(a2);
synchronized(a2){
Temp = a1.Balance;
a1.Balance = a2.Balance;
a2.Balance = Temp;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在性能方面有没有更好的实施?顺便说一下,这个线程安全吗?
您的代码会遇到死锁.如果线程swap(a2, a1)在另一个线程调用时调用swap(a1, a2),则会出现死锁.
您必须确保始终以相同的顺序锁定帐户.例如,假设所有帐户都由唯一ID标识,
public void swap(Account a1, Account a2) {
Account first = a1;
Account second = a2;
if (a1.getId().compareTo(a2.getId()) > 0) {
first = a2;
second = a1;
}
synchronized (first) {
synchronized (second) {
// swap the balances
}
}
}
Run Code Online (Sandbox Code Playgroud)
另一个大问题是您使用公共字段访问帐户余额.几乎从不使用公共字段,尤其是当多个线程访问对象时.使用访问器方法,并确保它们正确同步,或者其他线程在交换后不会看到新的余额.必须始终以同步方式访问每个共享状态.
但是,首先要对代码进行编译,并尊重Java命名约定.