Java-17.4同期の詳細を最初から認識(3)-オブジェクトロック

3789 ワード

この章では、前の章の問題に続いて、オブジェクトロックという解決策を示します.
1.オブジェクトロックとは?
オブジェクトロックとは、Javaが臨界領域synchronized(Object)文で指定したオブジェクトに対してロックをかけることであり、オブジェクトロックは排他的排他ロックである.
2.臨界区とは何ですか.
臨界領域とは、プログラム内のコードセグメントを指し、このコードでは、同じオブジェクトに単独で同時スレッドでアクセスします.Javaでは、キーワード「synchronized」で臨界領域を識別します.
3.一般的なオブジェクトロック:synchronizedとReentrantLock
次に、2つのコード例を示します(次の2つの例は、以前の銀行のコードに基づいて修正され、主にBankのコードを修正し、他のものは変更されません).
コード投稿接続:http://blog.csdn.net/raylee2007/article/details/50496784
修正されたコード:
synchronizedの使用
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の使用:
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元、総数:100000.00元5口座から転出   819.37元、92口座から振り込む   819.37元、総数:100000.00元12口座から転出  1278.62元、67口座から振り込む  1278.62元、総数:100000.00元3口座から転出  1353.74元、9口座から振り込む  1353.74元、総数:100000.00元94口座から転出  2316.07元、83口座から振り込む  2316.07元、総数:100000.00元59口座から転出  2563.51元、90口座から振り込む  2563.51元、総数:100000.00元82口座から転出  6276.89元、30口座から振り込む  6276.89元、総数:100000.00元2口座から転出  6175.01元、80口座から振り込む  6175.01元、総数:100000.00元21口座から転出  50300.61元、80口座から振り込む  50300.61元、総数:100000.00元
……(など)
出力により,総数はもはや変動せず,誤差は生じないことがわかる.
まとめ:この章では、主に同期の方法:オブジェクトロック、および一般的な2つのオブジェクトロックについて説明します.
この章はここまでです.ありがとうございます.
-----------------------------------
目次