源自–java核心技术
这里通过一个例子说明如何使用java中的同步,一个银行有100个账户,创建多个线程来执行随机从一个账户向另一个账户转账,未执行同步时执行结果输出银行总金额会出现差错,在使用同步之后,程序没有出现任何差错。代码如下:
import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Bank {
private final double[] accounts;
private Lock bankLock = new ReentrantLock();
private Condition sufficientFunds = bankLock.newCondition();
public Bank(int n, double initialBalance) {
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
}
public synchronized void transfer(int from, int to, double amount) throws InterruptedException {
bankLock.lock();
try {
while (accounts[from] < amount) wait();
System.out.println(Thread.currentThread());
accounts[from] -= amount;
System.out.printf("%10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance:%10.2f%n", getTotalBalance());
notifyAll();
} finally {
bankLock.unlock();
}
}
//第二种同步方法,不建议
/* public void transfer(int from, int to, double amount) throws InterruptedException {
bankLock.lock();
try {
while (accounts[from] < amount) sufficientFunds.await();
System.out.println(Thread.currentThread());
accounts[from] -= amount;
System.out.printf("%10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance:%10.2f%n", getTotalBalance());
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}*/
public double getTotalBalance () {
double sum = 0;
for (double a : accounts)
sum += a;
return sum;
}
public int size () {
return accounts.length;
}
}
public class UnsynchBankTest {
public static final int NACCOUNTS=100;
public static final double INITIAL_BALANCE=1000;
public static final double MAX_AMOUNT=1000;
public static final int DELAY=10;
public static void main(String[] args){
Bank bank=new Bank(NACCOUNTS,INITIAL_BALANCE);
for(int i=0;i<NACCOUNTS;i++){
int fromAccount=i;
Runnable r=()->{
try{
while(true){
int toAccount=(int)(bank.size()*Math.random());
double amount=MAX_AMOUNT*Math.random();
bank.transfer(fromAccount,toAccount,amount);
Thread.sleep((int)(DELAY*Math.random()));
}
}
catch (InterruptedException e){
}
};
Thread t=new Thread(r);
t.start();
}
}
}