Java并发编程实例--13.方法同步(synchronized)
使用synchronized关键字去控制对某个方法的并发调用。
某一时段内,只能有一个线程可以读取该方法。
其他线程需要等待前面线程调用完毕后方可调用。
不过,静态方法有着不同的行为。
虽然也是每次只能有一个线程调用它,但是另一个线程可以调用该类对象的其他非静态方法。
这一点需要注意,因为如果2个线程可读取2个不同的同步方法,一个是静态另一个不是。
如果这2个方法修改的是同样的数据,可能会导致数据不一致错误。
本例中,我们将有一个银行账户和2个线程;1个线程存钱,1个线程取钱。这种情况,如果不适用方法同步机制账户里的钱就不对了。方法同步机制保证了账户的最终平衡。
Account.java
package com.dylan.thread.ch2.c01.task;
/**
* This class simulates a bank account
*
*/
public class Account {
/**
* Balance of the bank account
*/
private double balance;
/**
* Returns the balance of the account
* @return the balance of the account
*/
public double getBalance() {
return balance;
}
/**
* Establish the balance of the account
* @param balance the new balance of the account
*/
public void setBalance(double balance) {
this.balance = balance;
}
/**
* Add an import to the balance of the account
* @param amount the import to add to the balance of the account
*/
public synchronized void addAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp+=amount;
balance=tmp;
}
/**
* Subtract an import to the balance of the account
* @param amount the import to subtract to the balance of the account
*/
public synchronized void subtractAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp-=amount;
balance=tmp;
}
}
Company.java
package com.dylan.thread.ch2.c01.task;
/**
* This class simulates a company that pays a salary an
* insert money into an account
*
*/
public class Company implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account the account affected by the operations
*/
public Company(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
public void run() {
for (int i=0; i<100; i++){
account.addAmount(1000);
}
}
}
Bank.java
package com.dylan.thread.ch2.c01.task;
/**
* This class simulates a bank or a cash dispenser that takes money
* from an account
*
*/
public class Bank implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account The account affected by the operations
*/
public Bank(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
public void run() {
for (int i=0; i<100; i++){
account.subtractAmount(1000);
}
}
}
Main.java
package com.dylan.thread.ch2.c01.core;
import com.dylan.thread.ch2.c01.task.Account;
import com.dylan.thread.ch2.c01.task.Bank;
import com.dylan.thread.ch2.c01.task.Company;
/**
* Main class of the example. It creates an account, a company and a bank
* to work with the account. The final balance is equal to the initial.
*
*/
public class Main {
/**
* Main method of the example
* @param args
*/
public static void main(String[] args) {
// Creates a new account ...
Account account=new Account();
// an initialize its balance to 1000
account.setBalance(1000);
// Creates a new Company and a Thread to run its task
Company company=new Company(account);
Thread companyThread=new Thread(company);
// Creates a new Bank and a Thread to run its task
Bank bank=new Bank(account);
Thread bankThread=new Thread(bank);
// Prints the initial balance
System.out.printf("Account : Initial Balance: %f\n",account.getBalance());
// Starts the Threads
companyThread.start();
bankThread.start();
try {
// Wait for the finalization of the Threads
companyThread.join();
bankThread.join();
// Print the final balance
System.out.printf("Account : Final Balance: %f\n",account.getBalance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
Account : Initial Balance: 1000.000000
deposit 1000, balance:2000.0
deposit 1000, balance:3000.0
withdraw 1000, balance:2000.0
withdraw 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
Account : Final Balance: 1000.000000