使用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