从头认识java-17.4 详解同步(3)-对象锁

这一章节我们接着上一章节的问题,给出一个解决方案:对象锁。

1.什么是对象锁?

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


2.什么是临界区?

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


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

我们下面给出两个代码例子(下面两个例子都是根据之前的银行的代码来修改的,主要修改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元,总数: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元

......(等等)


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


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




这一章节就到这里,谢谢。

-----------------------------------

目录

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值