疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java详解同步对象锁


 

   

  ,给出一个解决方案:对象锁。

  1.什么是对象锁?

  对象锁是指Java为临界区synchronized(Object)语句指定的对象进行加锁,对象锁是独占排他锁。

  2.什么是临界区?

  临界区是指程序中的一个代码段,在这段代码中,单独并发的线程对同一个对象进行访问。在Java中,用关键字“synchronized”标识一个临界区。

  3.常用的对象锁:synchronized和ReentrantLock

  我们下面给出两个代码例子(下面两个例子都是根据之前的银行的代码来修改的,主要修改Bank的代码,其他的不变):

  修改的代码:

  使用synchronized

  [java]

  package com.ray.ch17;

  public class Bank {

  private final double[] accounts;

  public double[] getAccounts() {

  return accounts;

  }

  public Bank(int n, double initBalance) {

  accounts = new double[n];

  for (int i = 0; i < accounts.length; i++) {

  accounts[i] = initBalance;

  }

  }

  public double getTotal() {

  double total = 0;

  for (int i = 0; i < accounts.length; i++) {

  total += accounts[i];

  }

  return total;

  }

  public synchronized void transfer(int fromAccount, int toAccount,

  double money) {

  if (accounts[fromAccount] < money) {

  return;

  }

  accounts[fromAccount] -= money;

  System.out.printf("从" + fromAccount + "账户转出%10.2f元,", money);

  accounts[toAccount] += money;

  System.out.printf("从" + toAccount + "账户转入%10.2f元,", money);

  System.out.printf("总数:%10.2f元", getTotal());

  System.out.println();

  }

  public int size() {

  return accounts.length;

  }

  }

  使用ReentrantLock:

  [java]

  package com.ray.ch17;

  import java.util.concurrent.locks.ReentrantLock;

  public class Bank {

  private final double[] accounts;

  private ReentrantLock reentrantLock = new ReentrantLock();

  public double[] getAccounts() {

  return accounts;

  }

  public Bank(int n, double initBalance) {

  accounts = new double[n];

  for (int i = 0; i < accounts.length; i++) {

  accounts[i] = initBalance;

  }

  }

  public double getTotal() {

  double total = 0;

  for (int i = 0; i < accounts.length; i++) {

  total += accounts[i];

  }

  return total;

  }

  public void transfer(int fromAccount, int toAccount, double money) {

  reentrantLock.lock();

  try {

  if (accounts[fromAccount] < money) {

  return;

  }

  accounts[fromAccount] -= money;

  System.out.printf("从" + fromAccount + "账户转出%10.2f元,", money);

  accounts[toAccount] += money;

  System.out.printf("从" + toAccount + "账户转入%10.2f元,", money);

  System.out.printf("总数:%10.2f元", getTotal());

  System.out.println();

  } finally {

  reentrantLock.unlock();

  }

  }

  public int size() {

  return accounts.length;

  }

  }

  通过测试代码输出:

  从16账户转出 6853.31元,从80账户转入 6853.31元,总数:1000000.00元

  从5账户转出 819.37元,从92账户转入 819.37元,总数:1000000.00元

  从12账户转出 1278.62元,从67账户转入 1278.62元,总数:1000000.00元

  从3账户转出 1353.74元,从9账户转入 1353.74元,总数:1000000.00元

  从94账户转出 2316.07元,从83账户转入 2316.07元,总数:1000000.00元

  从59账户转出 2563.51元,从90账户转入 2563.51元,总数:1000000.00元

  从82账户转出 6276.89元,从30账户转入 6276.89元,总数:1000000.00元

  从2账户转出 6175.01元,从80账户转入 6175.01元,总数:1000000.00元

  从21账户转出 5030.61元,从80账户转入 5030.61元,总数:1000000.00元

  ......(等等)

  通过输出可以看见,总数已经是不再变动,不再出现误差。

  总结:这一章节主要讨论了同步的方法:对象锁,以及常用的两个对象锁。