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();
}
}