public class Account {
/**优先存款方式*/
public static final int PREFER = 1;
/**普通存款方式*/
public static final int NORMAL = 2;
private int surplus;//结余
private int preferRequests;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public Account() {
surplus = 0;
preferRequests = 0;
}
/**
* 结余 += k
*
* @param k
*/
public void deposit(int k) {
lock.lock();
try {
surplus += k;
System.out.println("Thread " + Thread.currentThread().getName() + " deposit "+ k);
condition.signalAll();
} finally {
lock.unlock();
}
}
/**
* 当结余 >= k 时,结余 -= k
*
* @param k
*/
public void withdraw(int k, int style) {
lock.lock();
try {
if (style == NORMAL) {
//preferRequests>0 表示有优先的取款在等待,则普通取款不能进行下去
while (surplus < k || preferRequests > 0) {
condition.await();
}
surplus -= k;
System.out.println("Normale Thread " + Thread.currentThread().getName() + " withdraw "+ k);
} else if (style == PREFER) {
++preferRequests;
while (surplus < k) {
condition.await();
}
surplus -= k;
--preferRequests;
System.out.println("Prefer Thread " + Thread.currentThread().getName() + " withdraw "+ k);
condition.signalAll();
} else {
throw new InterruptedException();
}
} catch (InterruptedException e) {
e.printStackTrace();
condition.signalAll();
} finally {
lock.unlock();
}
}
/**
* 向另一个账户转账
* @param k 转账金额
* @param reserve
*/
public void transfer(int k,Account reserve){
lock.lock();
try {
reserve.withdraw(k,NORMAL);
deposit(k);
}finally {
lock.unlock();
}
}
}
private static void test_account() {
Account[] accounts = new Account[2];
for (int i = 0; i < accounts.length; ++i) {
accounts[i] = new Account();
}
TestAccountThread tester1 = new TestAccountThread(accounts[0], accounts[1]);
TestAccountThread tester2 = new TestAccountThread(accounts[1], accounts[0]);
tester1.start();
tester2.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("After sleep ");
for (Account account : accounts) {
account.deposit(1000);
}
}
(3)不一定全部会返回,因为可能在其他线程的condition上死锁,boss notify自己的锁线程感应不到。
测试结果:
线程tester1,tester2转账均失败,出现死锁