`

synchronized 关键字

阅读更多

java中每个对象都有一个隐式的锁,如果一个方法由synchronized关键字声明,那些对象的锁将保护整个方法。
也就是说,要调用这个方法,线程必须先获得对象的锁。
隐式对象锁只有一个关联条件。wait方法把线程加到等待集中,notify/notifyAll方法解除等待线程的阻塞状态。
也两个方法等价于Condition(条件变量)的await,signal/signalAll方法。

隐式的锁和条件存在一些缺点。如下:
1.不能中断一个正在试图获得锁的线程。
2.试图获得锁时不能设定超时。
3.每个锁只有一个条件有时候显得不够用。
4.虚拟机的加锁原语不能很好地映射到硬件可用的最有效的加锁机制上。

 

在下面三个条件下,对一个域的并行访问是安全的:
1.域是volatile的。
2.域是final的,并且在构造器调用完成后被访问。
3.对域的访问有锁保护。

 

 

银行转账例子:(出自《JAVA2核心技术第7版卷2高级特性》书中例子)

/** 
   This program shows how multiple threads can safely access a data structure, using 
   synchronized methods.
*/
public class SynchBankTest2
{  
   public static void main(String[] args)
   {  
      Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
      int i;
      for (i = 0; i < NACCOUNTS; i++)
      {  
         TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);
         Thread t = new Thread(r);
         t.start();
      }
   }

   public static final int NACCOUNTS = 100;
   public static final double INITIAL_BALANCE = 1000;
}

/**
   A bank with a number of bank accounts.
*/
class Bank
{ 
   /**
      Constructs the bank.
      @param n the number of accounts
      @param initialBalance the initial balance
      for each account
   */
   public Bank(int n, double initialBalance)
   {  
      accounts = new double[n];
      for (int i = 0; i < accounts.length; i++)
         accounts[i] = initialBalance;
   }

   /**
      Transfers money from one account to another.
      @param from the account to transfer from
      @param to the account to transfer to
      @param amount the amount to transfer
   */
   public synchronized void transfer(int from, int to, double amount)
      throws InterruptedException
   {  
      while (accounts[from] < amount)
         wait();
      System.out.print(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();
   }

   /**
      Gets the sum of all account balances.
      @return the total balance
   */
   public synchronized double getTotalBalance()
   {  
      double sum = 0;
      
      for (double a : accounts)
         sum += a;
      
      return sum;
   }

   /**
      Gets the number of accounts in the bank.
      @return the number of accounts
   */
   public int size()
   {
      return accounts.length;
   }

   private final double[] accounts;
}

/**
   A runnable that transfers money from an account to other
   accounts in a bank.
*/
class TransferRunnable implements Runnable
{ 
   /**
      Constructs a transfer runnable.
      @param b the bank between whose account money is transferred
      @param from the account to transfer money from
      @param max the maximum amount of money in each transfer 
   */
   public TransferRunnable(Bank b, int from, double max)
   {  
      bank = b;
      fromAccount = from;
      maxAmount = max;
   }

   public void run()
   {  
      try
      {  
         while (true)
         {  
            int toAccount = (int) (bank.size() * Math.random());
            double amount = maxAmount * Math.random();
            bank.transfer(fromAccount, toAccount, amount);
            Thread.sleep((int) (DELAY * Math.random()));
         }
      }
      catch (InterruptedException e) {}
   }

   private Bank bank;
   private int fromAccount;
   private double maxAmount;
   private int repetitions;
   private int DELAY = 10;
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics