java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。
我们来看java中第三种同步的方式,使用可重入的锁。
package com.farsight.thread3;
import java.util.concurrent.locks.ReentrantLock;
/**
* 封装账户编号,账户余额
* @author xj
*
*/
class Account{
// 定义一个可重入的锁对象
public final ReentrantLock lock = new ReentrantLock();
private String accountNo;
private double balance;
public Account(){
}
public Account(String accountNo, double balance){
this.accountNo = accountNo;
this.balance = balance;
}
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public double getBalance() {
return balance;
}
public void draw(double drawAmount){
// 加锁
lock.lock();
try{
// 账户余额大于取钱的数目
if(balance >= drawAmount){
System.out.println(Thread.currentThread().getName() + "取钱成功! 吐出钞票: " + drawAmount);
//人为制造cpu调度,使并发产生
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 修改余额
balance -= drawAmount;
}
else{
System.out.println(Thread.currentThread().getName() + "取钱失败!余额不足!");
}
}
finally {
// 释放锁
lock.unlock();
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((accountNo == null) ? 0 : accountNo.hashCode());
long temp;
temp = Double.doubleToLongBits(balance);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Account other = (Account) obj;
if (accountNo == null) {
if (other.accountNo != null)
return false;
}
else if (!accountNo.equals(other.accountNo))
return false;
if (Double.doubleToLongBits(balance) != Double
.doubleToLongBits(other.balance))
return false;
return true;
}
}
/**
* 定义一个取钱的线程类,该线程类根据执行账户、取钱
* 数量进行取钱操作,余额不足时无法提取现金。
* @author xj
*
*/
class DrawThread extends Thread{
// 定义一个用户类,取钱数量
private Account account;
private double drawAmount;
public DrawThread(String name, Account account, double drawAmount){
super(name);
this.account = account;
this.drawAmount = drawAmount;
}
public void run(){
account.draw(drawAmount);
}
}
public class ThreadDemon3 {
public static void main(String[] args) {
// 创建一个模拟户
Account acct = new Account("1234567", 10000);
//模拟两个线程对同一个账户取钱
new DrawThread("甲", acct, 6000).start();
new DrawThread("乙", acct, 5000).start();
}
}