java对多个对象加锁

java中存在对多个对象加锁的情况,例如: 在银行系统转账时,需要锁定两个账户,这个时候,顺序使用两个synchronized可能存在死锁的情况,在网上搜索到下面的例子:

public class Bank {
	final static Object obj_lock = new Object();

	// Deadlock crisis
	public void transferMoney(Account from, Account to, int number) {
		synchronized (from) {
			synchronized (to) {
				from.debit();
				to.credit();
			}
		}
	}

	// Thread safe
	public void transferMoney2(final Account from, final Account to, int number) {
		class Help {
			void transferMoney2() {
				from.debit();
				to.credit();
			}
		}

		int fromHash = from.hashCode();
		int toHash = to.hashCode();
		if (fromHash < toHash) {
			synchronized (from) {
				synchronized (to) {
					new Help().transferMoney2();
				}
			}
		} else if (toHash < fromHash) {
			synchronized (to) {
				synchronized (from) {
					new Help().transferMoney2();
				}
			}
		} else {
			synchronized (obj_lock) {
				synchronized (to) {
					synchronized (from) {
						new Help().transferMoney2();
					}
				}
			}
		}
	}
}


若操作账户A,B:
1 A的hashCode小于B, 先锁A再锁B
2 B的hashCode小于A, 先锁B再锁A
3 产生的hashCode相等,先锁住一个全局静态变量,在锁A,B

这样就避免了两个线程分别操作账户A,B和B,A而产生死锁的情况。

注意点:
  1 需要为Account对象写一个好的hashCode算法,使得不同账户间产生的hashCode尽量不同。
  2 如果某次产生hashCode相同锁住obj_lock,那么如果有新的操作再次产生相同hashCode,就必须等待前一次操作完成,可能产生性能问题。(这里应该有更好的方法)

你可能感兴趣的:(java,thread,算法)